import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;

public class PenjumlahanForkJoin {
    private static final int AMBANG = 1_000; // ukuran maksimum dihitung langsung

    // RecursiveTask<Long>: tugas rekursif yang mengembalikan nilai.
    private static class TugasJumlah extends RecursiveTask<Long> {
        private final int dari;
        private final int sampai;

        TugasJumlah(int dari, int sampai) {
            this.dari = dari;
            this.sampai = sampai;
        }

        @Override
        protected Long compute() {
            if (sampai - dari + 1 <= AMBANG) {
                long total = 0; // cukup kecil: jumlahkan berurutan
                for (int i = dari; i <= sampai; i++) {
                    total += i;
                }
                return total;
            }
            int tengah = (dari + sampai) / 2;
            TugasJumlah kiri = new TugasJumlah(dari, tengah);
            TugasJumlah kanan = new TugasJumlah(tengah + 1, sampai);
            kiri.fork();                     // antrekan paruh kiri ke pool
            long hasilKanan = kanan.compute(); // kerjakan paruh kanan sendiri
            long hasilKiri = kiri.join();      // tunggu dan ambil hasil kiri
            return hasilKiri + hasilKanan;
        }
    }

    public static void main(String[] args) throws Exception {
        long berurutan = 0; // patokan: penjumlahan satu thread
        for (int i = 1; i <= 10_000; i++) {
            berurutan += i;
        }
        System.out.println("penjumlahan berurutan : " + berurutan);

        ForkJoinPool pool = new ForkJoinPool();
        try {
            // invoke: kirim tugas teratas dan tunggu sampai selesai.
            long hasilInvoke = pool.invoke(new TugasJumlah(1, 10_000));
            System.out.println("fork/join via invoke  : " + hasilInvoke);

            // submit: kirim dulu, ambil hasilnya nanti lewat get().
            ForkJoinTask<Long> tugas = pool.submit(new TugasJumlah(1, 10_000));
            System.out.println("fork/join via submit  : " + tugas.get());
        } finally {
            pool.shutdown();
        }
    }
}
