JavaRush /Kurslar /All lectures for UZ purposes /ExecutorService To'xtatish

ExecutorService To'xtatish

All lectures for UZ purposes
Daraja, Dars
Mavjud

Eng oddiy dasturga nazar tashlaymiz:


public static void main(String[] args) throws Exception {
	// 3 ga teng bo'lgan fixer thread pool bilan ExecutorService yaratamiz
	ExecutorService service = Executors.newFixedThreadPool(3);
 
	// ExecutorService ga oddiy Runnable vazifasini uzatamiz
	service.submit(() -> System.out.println("bajarildi"));
}

Dastur ishga tushganda, konsolda kutilgan natija olinadi:

bajarildi

Lekin keyin IntellijIDEA uchun odatiy chiqishni ko'rmaymiz:

Jarayon tugatildi, chiqish kodi 0

Buni odatda dastur yakunida ko'rish mumkin.

Nima uchun shunday bo'lmoqda?

Metod newFixedThreadPool() tavsifidan, bu ExecutorService orqali yaratilgan iplar ochiq to'xtatilmaguncha mavjud bo'lishda davom etishini bilib olamiz. Demak, biz bir vazifani ExecutorService ga topshirganimizda, bu vazifani bajarish uchun ip yaratilgan va vazifa bajarilgandan keyin ham mavjud bo'lgan.

ExecutorService To'xtatish

Xo'sh, ExecutorService ortidan “yopish” (to'xtatish) zarur. Buni ikki usulda amalga oshirish mumkin:

  1. void shutdown() — bu metod chaqirilgandan so'ng ExecutorService yangi vazifalarni qabul qilmaydi. Oldinroq ExecutorService ga berilgan barcha vazifalar bajarilishini davom ettiradi.

    
    public static void main(String[] args) throws Exception {
    ExecutorService service = Executors.newFixedThreadPool(3);
        	service.submit(() -> System.out.println("vazifa 1"));
        	service.submit(() -> System.out.println("vazifa 2"));
        	service.shutdown();
        	// bu erda RejectedExecutionException sodir bo'ladi
        	service.submit(() -> System.out.println("vazifa 3"));
    }
    
  2. List<Runnable> shutdownNow() — metod mavjud faol vazifalarni to'xtatishga harakat qiladi. Qator kutib turgan vazifalar tashlanadi va Runnable ro'yxati shaklida qaytariladi.

    
    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);
    }
    

Dastur chiqishi:

1
2
4
3
java.util.concurrent.FutureTask@1e80bfe8[Not completed, task = java.util.concurrent.Executors$RunnableAdapter@4edde6e5[Wrapped task = Test$$Lambda$16/0x0000000800b95040@70177ecd]]
java.util.concurrent.FutureTask@cc34f4d[Not completed, task = java.util.concurrent.Executors$RunnableAdapter@66a29884[Wrapped task = Test$$Lambda$16/0x0000000800b95040@4769b07b]]
java.util.concurrent.FutureTask@6f539caf[Not completed, task = java.util.concurrent.Executors$RunnableAdapter@17a7cec2[Wrapped task = Test$$Lambda$16/0x0000000800b95040@65b3120a]]
5

Jarayon yakunlandi, chiqish kodi 0

Chiqish ishga tushirishdan ishga tushirishga farq qiladi. Chiqishda 2 xil satrlar mavjud:

  • raqam — bu vazifa ExecutorService tomonidan amalga oshirilgan va vazifalar ro'yxatidan raqam chiqarildi.

  • FutureTask turidagi ob'ekt, uning toString() metodi chaqirilgandan keyin. Bu ExecutorService ga topshirilgan vazifalar, lekin bajarilmagan.

Bu chiqishda yana bir qiziqarli narsa bor. Agar biz ideal dunyoda yashayotgan bo'lsak, barcha raqamlar birinchi chiqarilgan bo'lar edi va keyin FutureTask turidagi ob'ektlar. Ammo sinxronizatsiya muammolari tufayli chiqishdagi satrlar aralashgan.

Boshqa metodlar

Bundan tashqari, ExecutorService ni to'xtatish bilan bog'liq yana bir nechta metodlar mavjud:

  1. boolean awaitTermination(long timeout, TimeUnit unit) — metod uni chaqirgan ipni bloklaydi. Blokirovka quyidagi uchta voqeadan biri sodir bo'lganda bekor qilinadi:

    • shutdown() metodi chaqirilgandan so'ng, barcha faol vazifalar va navbatdagi barcha vazifalar bajarildi;
    • metod parametrlari orqali belgilangan vaqtdan o'tdi;
    • awaitTermination() metodini chaqirgan ip uzildi.

    Metod true qaytaradi, agar ExecutorService timeout tugashidan oldin to'xtatilgan bo'lsa, va false, agar timeout oldinroq tugagan bo'lsa.

    
    public static void main(String[] args) throws Exception {
    	ExecutorService service = Executors.newFixedThreadPool(2);
    	service.submit(() -> System.out.println("vazifa 1"));
    	service.submit(() -> System.out.println("vazifa 2"));
    	service.submit(() -> System.out.println("vazifa 3"));
    	service.shutdown();
    	System.out.println(service.awaitTermination(1, TimeUnit.MICROSECONDS));
    }
    
  2. boolean isShutdown() — true qaytaradi, agar ExecutorService ga shutdown() yoki shutdownNow() metodi chaqirilgan bo'lsa.

    
    public static void main(String[] args) throws Exception {
    	ExecutorService service = Executors.newFixedThreadPool(2);
    	service.submit(() -> System.out.println("vazifa 1"));
    	service.submit(() -> System.out.println("vazifa 2"));
    	service.submit(() -> System.out.println("vazifa 3"));
    	System.out.println(service.isShutdown());
    	service.shutdown();
    	System.out.println(service.isShutdown());
    }
    
  3. boolean isTerminated() — true qaytaradi, agar ExecutorService ga shutdown() yoki shutdownNow() chaqirilib, barcha vazifalar bajarilgan bo'lsa.

    
    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());
    }
    

Ko'rib chiqilgan metodlardan foydalanilgan kod namunasi:


public static void main(String[] args) throws Exception {
   ExecutorService service = Executors.newFixedThreadPool(16);
   Callable<String> task = () -> {
       Thread.sleep(1);
       return "Tugadi";
   };
 
   // 10 mingta vazifani bajarishga qo'shamiz
   List<Future<String>> futures = IntStream.range(0, 10_000)
           .mapToObj(i -> service.submit(task))
           .collect(Collectors.toList());
   System.out.printf("Bajarishga yuborilgan %d vazifalar.%n", futures.size());
 
   // yopishga harakat qilamiz
   service.shutdown();
   // 100 millisekund davomida ishning tugashini kutamiz
   if (service.awaitTermination(100, TimeUnit.MILLISECONDS)) {
       System.out.println("Barcha vazifalar bajarildi!");
   } else {
       // majburan to'xtatamiz
       List<Runnable> notExecuted = service.shutdownNow();
       System.out.printf("Ishga tushmagan %d vazifalar.%n", notExecuted.size());
   }
 
   System.out.printf("Jami bajarilgan %d vazifalar.%n", futures.stream().filter(Future::isDone).count());
}

Dastur chiqishi (ishga tushirishdan ishga tushirishga farq qiladi):

Bajarishga yuborilgan 10000 vazifalar.
Ishga tushmagan 9170 vazifalar.
Jami bajarilgan 830 vazifalar.

Jarayon yakunlandi, chiqish kodi 0
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION