import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;

public class AksiKaliDua {
    private static final int AMBANG = 1_000;

    // RecursiveAction: tugas rekursif TANPA nilai balik -- hasil
    // tersimpan pada efek sampingnya (array yang digandakan).
    private static class AksiGandakan extends RecursiveAction {
        private final int[] data;
        private final int dari;
        private final int sampai; // batas atas eksklusif

        AksiGandakan(int[] data, int dari, int sampai) {
            this.data = data;
            this.dari = dari;
            this.sampai = sampai;
        }

        @Override
        protected void compute() {
            if (sampai - dari <= AMBANG) {
                for (int i = dari; i < sampai; i++) {
                    data[i] *= 2;
                }
                return;
            }
            int tengah = (dari + sampai) / 2;
            AksiGandakan kiri = new AksiGandakan(data, dari, tengah);
            AksiGandakan kanan = new AksiGandakan(data, tengah, sampai);
            invokeAll(kiri, kanan); // fork keduanya, tunggu keduanya selesai
        }
    }

    public static void main(String[] args) {
        int[] data = new int[8_000];
        for (int i = 0; i < data.length; i++) {
            data[i] = i + 1;
        }
        long sebelum = 0;
        for (int nilai : data) {
            sebelum += nilai;
        }

        ForkJoinPool pool = new ForkJoinPool();
        try {
            pool.invoke(new AksiGandakan(data, 0, data.length));
        } finally {
            pool.shutdown();
        }

        long sesudah = 0;
        for (int nilai : data) {
            sesudah += nilai;
        }
        System.out.println("jumlah sebelum         : " + sebelum);
        System.out.println("jumlah sesudah         : " + sesudah);
        System.out.println("semua elemen digandakan: " + (sesudah == sebelum * 2));
    }
}
