JavaRush /Kurslar /All lectures for UZ purposes /ExecutorService interfeysi

ExecutorService interfeysi

All lectures for UZ purposes
Daraja, Dars
Mavjud

Executor interfeysining maqsadi

Java 5'ga qadar oqimlarni boshqarish uchun butun kodni o'zingiz yozishingiz kerak edi. Bundan tashqari, new Thread obyektini yaratish — bu resurs talabi yuqori bo'lgan operatsiya, va “yengil vaznli” vazifalar uchun har safar yangi oqim yaratish mantiqli emas edi. Va chunki bu muammoga ko'p oqimli ilovalarni ishlab chiquvchilar duch kelgan, bu funksiyani Java'da Executor freymvorki sifatida ajratishga qaror qildilar.

Asosiy g'oya nima? Juda oddiy: har bir yangi vazifa uchun yangi oqim yaratish o'rniga, oqimlar qandaydir "xotira"da saqlanadi va yangi vazifa kelganda, mavjud oqim olinadi, yangi yaratilmaydi.

Ushbu freymvorkning asosiy interfeyslari — Executor, ExecutorService va ScheduledExecutorService, har biri avvalgisidan ko'proq imkoniyatga ega.

Executor interfeysi — bu asosiy interfeys bo'lib, faqat bitta metodni e'lon qiladi: void execute(Runnable command) — vazifani ishga tushirish uchun, u Runnable tipidagi obyekt bilan ta'riflanadi.

ExecutorService interfeysi esa qiziqarliroq, chunki bu interfeysda ishni tugatishni boshqarish uchun metodlar mavjud va ba'zi resultatlarni qaytaradigan metodlar ham bor. Uning metodlari yanada batafsil:

Metod Tavsifi
void shutdown(); Ushbu metodni chaqirish ExecutorServiceni to'xtatishni boshlaydi. Barcha oldin yuborilgan vazifalar yakunlanadi, yangi vazifalar qabul qilinmaydi.
List<Runnable> shutdownNow();

Ushbu metodni chaqirish ExecutorServiceni to'xtatishni boshlaydi. Barcha oldin yuborilgan vazifalar Thread.interrupt buyruqini oladi. Navbatda turgan vazifalar natija sifatida qaytarilgan metodning chaqiruv natijasi sifatida qaytariladi.

Metod "ishlayotgan" vazifalarning barcha ishlarini tugatishni kutmaydi va chaqirilgan paytda bajarilayotgan vazifalarga ta'sir qilmasligi mumkin.

E'tibor bering: metodni chaqirish resurslarni sarflashga olib kelishi mumkin.

boolean isShutdown(); ExecutorService to'xtatilganligini tekshiradi.
boolean isTerminated(); ExecutorService to'xtatilgandan so'ng barcha vazifalar bajarilgan bo'lsa, true ni qaytaradi. shutdown() yoki shutdownNow() metodi chaqirilguncha, har doim false ni qaytaradi.
boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;

Ushbu metodni chaqirgandan so'ng, shutdown() chaqirilgandan so'ng, oqimni bloklaydi, quyidagi shartlardan biri sodir bo'lguncha:

  • barcha rejalashtirilgan vazifalar bajariladi;
  • metod parametrlari sifatida ko'rsatilgan vaqt oralig'i o'tadi;
  • joriy oqim o'z ishini to'xtatadi.

Barcha vazifalar tugagan bo'lsa true ni va oldinroq time out holati sodir bo'lsa false ni qaytaradi.

<T> Future<T> submit(Callable<T> task);

ExecutorService chaqiriladigan (Callable) vazifani qo'shadi va Future interfeysini amalga oshiradigan obyektni qaytaradi.

<T> — berilgan vazifaning natija turi.

<T> Future<T> submit(Runnable task, T result);

ExecutorService bajariladigan (Runnable) vazifani qo'shadi va Future interfeysini amalga oshiradigan obyektni qaytaradi.

T result parametri — Future obyektidan get() metodini chaqirish natijasi.

Future<?> submit(Runnable task);

ExecutorService bajariladigan (Runnable) vazifani qo'shadi va Future interfeysini amalga oshiradigan obyektni qaytaradi.

Agar olingan obyekt Futuredan get() metodini chaqirsak, null ni qaytaradi.

<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException;

ExecutorService chaqiriladigan (Callable) vazifalar ro'yxatini uzatadi. Natijani olish uchun Future ro'yxatini qaytaradi. Ushbu ro'yxat barcha o'tgan vazifalar bajarilgandan so'ng qaytariladi.

Agar metod ishlayotgan vaqtida tasks kolleksiyasini o'zgartirsangiz, metod natijasi aniq emas.

<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException;

ExecutorService chaqiriladigan (Callable) vazifalar ro'yxatini uzatadi. Natijani olish uchun Future ro'yxatini qaytaradi. Bu roʻyxat barcha vazifalar tugaganidan soʻng yoki metod parametrlarida berilgan vaqt oʻtganidan soʻng (qaysi biri avval keladi) qaytariladi.

Agar taym-aut avval kelib qolsa, bajarilmagan vazifalar o'z ishlarini bekor qilishadi.

Eslatma: bekor qilingan vazifa o'z ishini to'xtatmasligi va ishlashda davom etishi mumkin (bu yon ta'sirni misolda ko'ramiz).

Agar metod ishlayotgan vaqtida tasks kolleksiyasini o'zgartirsangiz, metod natijasi aniq emas.

<T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException;

ExecutorService chaqiriladigan (Callable) vazifalar ro'yxatini uzatadi. Istisno tashlamasdan bajarilgan (agar topilgan bo'lsa) vazifalarning natijasini qaytaradi.

Agar metod ishlayotgan vaqtida tasks kolleksiyasini o'zgartirsangiz, metod natijasi aniq emas.

<T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;

ExecutorService chaqiriladigan (Callable) vazifalar ro'yxatini uzatadi. Istisno tashlamasdan bajarilgan (agar topilgan bo'lsa) vazifalarning natijasini qaytaradi, metod parametrlarida belgilangan vaqt tugashidan oldin.

Agar metod ishlayotgan vaqtida tasks kolleksiyasini o'zgartirsangiz, metod natijasi aniq emas.

Keling, ExecutorService bilan ishlashning kichik bir misolini ko'rib chiqamiz.


import java.util.List;
import java.util.concurrent.*;

public class ExecutorServiceTest {
   public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
// 2 oqimlik ExecutorService yaratamiz
       java.util.concurrent.ExecutorService executorService = new ThreadPoolExecutor(2, 2, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10));
// 5 ta vazifa yaratamiz
       MyRunnable task1 = new MyRunnable();
       MyRunnable task2 = new MyRunnable();
       MyRunnable task3 = new MyRunnable();
       MyRunnable task4 = new MyRunnable();
       MyRunnable task5 = new MyRunnable();

       final List<MyRunnable> tasks = List.of(task1, task2, task3, task4, task5);
// 5 ta oldin yaratilgan vazifalarni o'z ichiga olgan ro'yxatni qayta ishlash uchun yuboramiz
       final List<Future<Void>> futures = executorService.invokeAll(tasks, 6, TimeUnit.SECONDS);
       System.out.println("got futures");

// ExecutorService ni to'xtatamiz
       executorService.shutdown();

       try {
           TimeUnit.SECONDS.sleep(3);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       System.out.println(executorService.isShutdown());
       System.out.println(executorService.isTerminated());
   }

   public static class MyRunnable implements Callable<Void> {

       @Override
       public Void call() {
// 2 ta vaqt kechikishini qo'shamiz. ExecutorService ni to'xtatishda vazifa bajarishni to'xtatishga urinishda qaysi ulardan biri ishlayotganini ko'ramiz
           try {
               TimeUnit.SECONDS.sleep(3);
           } catch (InterruptedException e) {
               System.out.println("sleep 1: " + e.getMessage());
           }
           try {
               TimeUnit.SECONDS.sleep(2);
           } catch (InterruptedException e) {
               System.out.println("sleep 2: " + e.getMessage());
           }
           System.out.println("done");
           return null;
       }
   }
}

Dastur chiqishi:

done
done
got futures
sleep 1: sleep interrupted
sleep 1: sleep interrupted
done
done
true
true

Har bir vazifa 5 sekund davom etadi. Ikkita oqimli pool yaratganimiz uchun dastlabki ikkita chiziq aniq va tushunarli.

Dastur ishga tushganidan 6 sekund o'tgach, invokeAll metodining taym-auti sodir bo'ladi va Future ro'yxati sifatida natija qaytariladi. Bu "got futures" chizig'i chiqishini ko'rsatadi.

Birinchi ikkita vazifa yakunlangandan so'ng, yana ikkita vazifa ishlay boshladi. Lekin metodda ko'rsatilgan vaqt o'tgani uchun invokeAll, bu ikkita vazifa tugashga ulgursalari, "bekor" buyruqini olishdi. Shu sababli chiqishlarda ikkita satr “sleep 1: sleep interrupted” ko'rinadi.

Keyin yana ikkita “done” yozuvini ko'rishimiz mumkin. Bu invokeAll metodini ta'riflashda yozgan yon ta'sir ko'rsatmasining namunasidir.

Beshinchi vazifa umuman ishga tushmagan, shuning uchun biz dastur chiqishida u haqida hech narsa ko'rmaymiz.

Oxirgi ikki qator - bu isShutdown va isTerminated metodlari chaqiruvining natijalarini ko'rsatadi.

Ushbu misolda taym-autning tugashidan so'ng (kodni "executorService.shutdown();") qatorida brekpoint qo'yib, vazifalarning holatini debagda ko'rishga qiziq:

Ko'rib turibmizki, ikkita vazifa tugadi: "Completed normally", va uchta vazifa "Cancelled".

ScheduledExecutorService

Ekzekyutorlar haqida hikoyani yakunlash uchun, ScheduledExecutorService haqida ham gaplashamiz.

Bu interfeysda 4 ta metod mavjud:

Metod Tavsifi
public ScheduledFuture<?> schedule(Runnable command,long delay, TimeUnit unit); Berilgan bajariladigan (Runnable) vazifani parametr sifatida berilgan vaqt oralig'ida bir martalik bajarayotganini rejalaydi.
public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit); Berilgan chaqiriladigan (Callable) vazifani parametr sifatida belgilangan vaqt oralig'ida bir martalik bajarayotganini rejalaydi.
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit); Bajarilgan vazifani periodik ravishda rejalashtiradi, birinchi ish initialDelaydan keyin amalga oshadi, har bir keyingi ish perioddan boshlanadi.
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit); Bajarilgan vazifani periodik ravishda rejalashtiradi, birinchi ish initialDelaydan keyin amalga oshadi, har bir keyingi ish o'tgan ish tugaganidan keyin delaydan boshlanadi.
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION