JavaRush /Kurslar /All lectures for UZ purposes /Метод newSingleThreadExecutor

Метод newSingleThreadExecutor

All lectures for UZ purposes
Daraja, Dars
Mavjud

1 ta oqimlik ExecutorService nima uchun kerak bo'lishi mumkin?

Executors.newSingleThreadExecutor metodi orqali faqat bitta oqimlik ExecutorService yaratishimiz mumkin. Bu poolning ishlash logikasi quyidagicha:

  • Xizmat bir vaqtning o'zida faqat bitta vazifani bajaradi.
  • Agar biz N ta vazifani yuborsak, barcha N ta vazifalar ketma-ket bitta oqim orqali bajariladi.
  • Agar oqim to'xtatilsa, qolgan vazifalarni bajarish uchun yangi oqim yaratiladi.

Bizning dasturimiz quyidagi funksionalni talab qilayotgan vaziyatni tasavvur qilaylik:

Bizga 30 soniya davomida foydalanuvchilardan kelayotgan so'rovlarni qayta ishlash kerak, ammo bir vaqtning o'zida faqat bitta so'rovni.

Foydalanuvchi so'rovini qayta ishlash vazifasini yaratamiz:


class Task implements Runnable {
   private final int taskNumber;

   public Task(int taskNumber) {
       this.taskNumber = taskNumber;
   }

   @Override
   public void run() {
       try {
           Thread.sleep(1000);
       } catch (InterruptedException ignored) {
       }
       System.out.printf("So'rov #%d id=%d oqimda qayta ishlangan\n", taskNumber, Thread.currentThread().getId());
   }
}
    

Bu klass kelgan so'rovning qayta ishlanishini va uning raqamini chiqaradi.

Keyin main metodida biz bitta oqimlik ExecutorService yaratamiz va kelgan so'rovlarni ketma-ket qayta ishlaymiz. 30 soniya davomida qayta ishlash ko'rsatilgani uchun, 30 soniya tugagach, biz ExecutorService ni majburiy to'xtatamiz.


public static void main(String[] args) throws InterruptedException {
   ExecutorService executorService = Executors.newSingleThreadExecutor();

   for (int i = 0; i < 1_000; i++) {
       executorService.execute(new Task(i));
   }
   executorService.awaitTermination(30, TimeUnit.SECONDS);
   executorService.shutdownNow();
}
    

Ishga tushirganda biz konsolda quyidagi xabarlarni ko'ramiz:

So'rov #0 id=16 oqimda qayta ishlangan
So'rov #1 id=16 oqimda qayta ishlangan
So'rov #2 id=16 oqimda qayta ishlangan
….
So'rov #29 id=16 oqimda qayta ishlangan

30 soniya davomida so'rovlar qayta ishlangandan so'ng executorService da shutdownNow() metodi chaqiriladi, bu joriy vazifani to'xtatadi va bajarishni kutayotgan barcha vazifalarni bekor qiladi. Shundan keyin dastur muvaffaqiyatli tugashini ko'ramiz.

Agar biron vazifa noto'g'ri bajarilib, hatto bizning yagona puldagi oqimimizni ham tugatsagina, bu har doim ham mukammal bo'lmaydi. Biz bunday vaziyatni simulyatsiya qilamiz, bu bizning yagona oqim bilan ExecutorService qanday ishlashini tushunishga yordam beradi.

Buning uchun vazifalardan biri bajarilayotganda eskirgan va xavfli Thread.currentThread().stop() metodi yordamida oqimimizni tugatamiz. Biz buni aynan oqimning bir vazifasi ustida tugashini simulyatsiya qilish uchun qilamiz.

Task klassidagi run metodini o'zgartiramiz:


@Override
public void run() {
   try {
       Thread.sleep(1000);
   } catch (InterruptedException ignored) {
   }

   if (taskNumber == 5) {
       Thread.currentThread().stop();
   }

   System.out.printf("So'rov #%d id=%d oqimda qayta ishlangan\n", taskNumber, Thread.currentThread().getId());
}
    

Biz 5-raqamli vazifada to'xtatamiz.

Oqimning 5-raqamli vazifa tugashida to'xtatilganidan keyingi chiqishni ko'ramiz:

So'rov #0 id=16 oqimda qayta ishlangan
So'rov #1 id=16 oqimda qayta ishlangan
So'rov #2 id=16 oqimda qayta ishlangan
So'rov #3 id=16 oqimda qayta ishlangan
So'rov #4 id=16 oqimda qayta ishlangan
So'rov #6 id=17 oqimda qayta ishlangan
So'rov #7 id=17 oqimda qayta ishlangan
…
So'rov #29 id=17 oqimda qayta ishlangan

Ko'ramizki, 5-vazifa tugashi bilan oqim id=16 dan id=17 ga o'tdi. Bu - executorService to'xtatilgan oqimni yangisiga almashtirib, vazifalar davom etmoqda.

newSingleThreadExecutor dan foydalanish ketma-ket vazifalarni bajarish uchun zarur va bu faqat bitta vazifa bir vaqtning o'zida bajarilgan vaziyatda talab qilinadi, lekin navbatdagi vazifalarni bajarishda davom etma majburiyatini qoldiradi, hatto vazifa qanday tugashidan qat'i nazar (bir vazifada oqim o'lib qolishi mumkin) bo'lsa ham.

ThreadFactory

Oqimlarni yaratish va qayta yaratish haqida gapirganda, biz ThreadFactory haqida ham ayta olmaymiz.

ThreadFactory — bu talab bo'yicha yangi oqimlar yaratadigan ob'ekt.

Biz o'z oqimlarimiz fabrikasini yaratib, uni Executors.newSingleThreadExecutor(ThreadFactory threadFactory) metodiga uzatishimiz mumkin.


ExecutorService executorService = Executors.newSingleThreadExecutor(new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r, "MyThread");
            }
        });
                    
Yangi oqim yaratish metodini konstruktorida nom berib qayta yozdik.

ExecutorService executorService = Executors.newSingleThreadExecutor(new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r, "MyThread");
                thread.setPriority(Thread.MAX_PRIORITY);
                return thread;
            }
        });
                    
Yaratilayotgan oqim uchun nom va prioritetni o'zgartirdik.

Shunday qilib, Executors.newSingleThreadExecutor ning ikki xil bo'lgan metodlari mavjudligini aniqladik. Biri - parametrsiz, ikkinchisi - ThreadFactory tipidagi parametr bilan.

ThreadFactory yordamida yaratilayotgan oqimlarni turli sozlamalar bilan ta'minlash mumkin, masalan, - prioritetlarni o'rnatish, oqimlar osti klasslarini ishlatish, UncaughtExceptionHandler oqimi qo'shish va hokazo.

Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION