Coba program prasaja:

public static void main(String[] args) throws Exception {
	// Create an ExecutorService with a fixed number of threads: three
	ExecutorService service = Executors.newFixedThreadPool(3);

	// Pass a simple Runnable task to the ExecutorService
	service.submit(() -> System.out.println("done"));
}

Ngaktifake program ngasilake output konsol sing dikarepake:

rampung

Nanging iki ora diterusake karo output sing biasane katon ing IntelliJ IDEA:

Proses rampung kanthi kode metu 0

Biasane kita weruh yen program rampung.

Yagene kedadeyan kasebut?

Katrangan cara newFixedThreadPool () ngandhani yen benang sing digawe nggunakake ExecutorService terus ana nganti mandheg kanthi jelas. Iki tegese amarga kita ngirim tugas menyang ExecutorService , thread digawe kanggo nglakokake, lan thread kasebut terus ana sanajan tugas wis rampung.

Mungkasi ing ExecutorService

Akibaté, kita kudu "mati" (utawa mungkasi) ExecutorService . Kita bisa nindakake iki kanthi rong cara:

  1. void shutdown () - sawise cara iki diarani, ExecutorService mandheg nampa proyek anyar. Kabeh tugas sing sadurunge dikirim menyang ExecutorService bakal terus mlaku.

    public static void main(String[] args) throws Exception {
    ExecutorService service = Executors.newFixedThreadPool(3);
        	service.submit(() -> System.out.println("task 1"));
        	service.submit(() -> System.out.println("task 2"));
        	service.shutdown();
        	// A RejectedExecutionException will occur here
        	service.submit(() -> System.out.println("task 3"));
    }
  2. List<runnable> shutdownNow() - Cara iki nyoba kanggo mungkasi proyek sing lagi aktif. Tugas sing isih ngenteni giliran dibuwang lan dibalekake minangka dhaptar Runnables .

    public static void main(String[] args) throws Exception {
        ExecutorService service = Executors.newFixedThreadPool(5);
        List.of(1, 2, 3, 4, 5, 6, 7, 8).forEach(i -> service.submit(() -> System.out.println(i)));
        List<Runnable> runnables = service.shutdownNow();
        runnables.forEach(System.out::println);
    }

Output:

1
2
4
3
java.util.concurrent.FutureTask@1e80bfe8[Ora rampung, tugas = java.util.concurrent.Executors$RunnableAdapter@4edde6e5[Tugas dibungkus = Test$$Lambda$16/0x0000000800b95070@70170@java
. .FutureTask@cc34f4d[Ora rampung, tugas = java.util.concurrent.Executors$RunnableAdapter@66a29884[Tugas sing dibungkus = Test$$Lambda$16/0x0000000800b95040@4769b07b]concurrent.6f000@4769b07b]FutureTask@cc34f4d
tugas = java.util.concurrent.Executors$RunnableAdapter@17a7cec2[Tugas dibungkus = Test$$Lambda$16/0x0000000800b95040@65b3120a]]
5

Proses rampung nganggo kode metu 0

Output bakal beda-beda saka run to run. Ana 2 jinis garis ing output:

  • Nomer tegese ExecutorService bisa ngolah tugas sing cocog, nampilake nomer saka dhaptar sing digunakake kanggo nggawe tugas.

  • Asil nelpon cara toString () ing obyek FutureTask . Objek kasebut minangka tugas sing dikirim menyang ExecutorService nanging ora diproses.

Output nduweni nuansa menarik liyane. Ing donya becik, kita bakal pisanan ndeleng kabeh nomer ditampilake, ngiring dening obyek FutureTask . Nanging masalah sinkronisasi jumble garis ing output.

Cara liyane

ExecutorService duwe sawetara cara liyane sing ana gandhengane kanggo mungkasi:

  1. boolean awaitTermination(wektu entek dawa, unit TimeUnit) - cara iki mblokir thread sing nyebataken. Pamblokiran rampung sanalika salah siji saka telung acara ing ngisor iki kedadeyan:

    • sawise mati () cara disebut, kabeh proyek aktif lan kabeh tugas dijadwal wis kaleksanan;
    • wektu entek ditemtokake dening paramèter cara wis liwati;
    • Utas sing disebut awaitTermination () cara wis mungkasi.

    Cara kasebut ngasilake bener yen ExecutorService mandheg sadurunge wektu entek, lan salah yen wektu entek wis liwati.

    public static void main(String[] args) throws Exception {
    	ExecutorService service = Executors.newFixedThreadPool(2);
    	service.submit(() -> System.out.println("task 1"));
    	service.submit(() -> System.out.println("task 2"));
    	service.submit(() -> System.out.println("task 3"));
    	service.shutdown();
    	System.out.println(service.awaitTermination(1, TimeUnit.MICROSECONDS));
    }
  2. boolean isShutdown () - Ngasilake bener yen shutdown () utawa shutdownNow () cara wis disebut ing ExecutorService .

    public static void main(String[] args) throws Exception {
    	ExecutorService service = Executors.newFixedThreadPool(2);
    	service.submit(() -> System.out.println("task 1"));
    	service.submit(() -> System.out.println("task 2"));
    	service.submit(() -> System.out.println("task 3"));
    	System.out.println(service.isShutdown());
    	service.shutdown();
    	System.out.println(service.isShutdown());
    }
  3. boolean isTerminated () - Ngasilake bener yen shutdown () utawa shutdownNow () cara wis disebut ing ExecutorService lan kabeh tugas wis rampung.

    public static void main(String[] args) throws Exception {
        ExecutorService service = Executors.newFixedThreadPool(5);
        List.of(1, 2, 3, 4, 5, 6, 7, 8).forEach(i -> service.submit(() -> System.out.println(i)));
        service.shutdownNow();
        System.out.println(service.isTerminated());
    }

Kode conto sing nggunakake cara iki:

public static void main(String[] args) throws Exception {
   ExecutorService service = Executors.newFixedThreadPool(16);
   Callable<String> task = () -> {
       Thread.sleep(1);
       return "Done";
   };

   // Add 10,000 tasks to the queue
   List<Future<String>> futures = IntStream.range(0, 10_000)
           .mapToObj(i -> service.submit(task))
           .collect(Collectors.toList());
   System.out.printf("%d tasks were submitted for execution.%n", futures.size());

   // Attempt to shut down
   service.shutdown();
   // Wait 100 milliseconds to finish the work
   if (service.awaitTermination(100, TimeUnit.MILLISECONDS)) {
       System.out.println("All tasks completed!");
   } else {
       // Stop forcibly
       List<Runnable> notExecuted = service.shutdownNow();
       System.out.printf("%d tasks were not started.%n", notExecuted.size());
   }

   System.out.printf("Total tasks completed: %d.%n", futures.stream().filter(Future::isDone).count());
}

Output (beda saka run to run):

10.000 tugas diajukake kanggo eksekusi.
9170 tugas ora diwiwiti.
Total tugas rampung: 830 tugas.

Proses rampung kanthi kode metu 0