Napa sampeyan mbutuhake ExecutorService kanggo 1 utas?

Sampeyan bisa nggunakake cara Executors.newSingleThreadExecutor kanggo nggawe ExecutorService karo blumbang sing kalebu thread siji. Logika blumbang kaya ing ngisor iki:

  • Layanan nglakokaké mung siji tugas ing wektu.
  • Yen kita ngirim tugas N kanggo eksekusi, kabeh tugas N bakal dieksekusi siji-sijine kanthi benang siji.
  • Yen utas diganggu, utas anyar bakal digawe kanggo nglakokake tugas sing isih ana.

Ayo bayangake kahanan ing ngendi program kita mbutuhake fungsi ing ngisor iki:

Kita kudu ngolah panjalukan pangguna sajrone 30 detik, nanging ora luwih saka siji panjalukan saben unit wektu.

Kita nggawe kelas tugas kanggo ngolah panjaluk pangguna:


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("Processed request #%d on thread id=%d\\n", taskNumber, Thread.currentThread().getId());
   }
}
    

Kelas kasebut nggawe model prilaku ngolah panjaluk sing mlebu lan nampilake nomer kasebut.

Sabanjure, ing cara utama , kita nggawe ExecutorService kanggo 1 utas, sing bakal digunakake kanggo ngolah panjalukan sing mlebu kanthi urutan. Amarga kahanan tugas kasebut "ing 30 detik", kita nambahake ngenteni 30 detik lan banjur mandhegake ExecutorService kanthi paksa .


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

Sawise miwiti program, console nampilake pesen babagan pangolahan panjalukan:

Panjaluk sing diproses #0 ing id utas=16
Panjaluk sing diproses #1 ing id utas=16
Panjaluk sing diproses #2 ing id utas=16

Panjaluk sing diproses #29 ing id utas=16

Sawise ngolah panjalukan kanggo 30 detik, executorService nelpon cara shutdownNow () , sing mandheg tugas saiki (sing dieksekusi) lan mbatalake kabeh tugas sing ditundha. Sawise iku, program rampung kanthi sukses.

Nanging kabeh ora mesthi sampurna, amarga program kita bisa kanthi gampang duwe kahanan ing ngendi salah sawijining tugas sing dijupuk dening benang mung blumbang ora bisa digunakake lan malah mungkasi thread kita. Kita bisa simulasi kahanan iki kanggo mangerteni carane executorService dianggo karo thread siji ing kasus iki.

Kanggo nindakake iki, nalika siji saka tugas lagi kaleksanan, kita siksa thread nggunakake cara Thread.currentThread ().stop () ora aman lan lungse . Kita nindakake iki kanthi sengaja kanggo niru kahanan ing ngendi salah sawijining tugas mungkasi thread kasebut.

Kita bakal ngganti cara run ing kelas Tugas :


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

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

   System.out.printf("Processed request #%d on thread id=%d\\n", taskNumber, Thread.currentThread().getId());
}
    

Kita bakal ngganggu tugas #5.

Ayo ndeleng apa output katon kaya thread sing diselani ing mburi tugas #5:

Panjaluk sing diproses #0 ing id utas=16
Panjaluk sing diproses #1 ing id utas=16
Panjaluk sing diproses #2 ing id utas=16
Panjaluk sing diproses #3 ing id utas=16
Panjaluk sing diproses #4 ing id utas=16 Panjaluk
sing diproses #6 ing id utas=17
Panjaluk sing diproses #7 ing id utas=17

Panjaluk sing diproses #29 ing id utas=17

Kita weruh yen sawise thread diselani ing mburi tugas 5, tugas wiwit dieksekusi ing thread sing pengenal 17, sanajan sadurunge wis dieksekusi ing thread karo pengenal 16. Lan amarga blumbang kita duwe thread siji, iki mung bisa ateges siji bab: executorService ngganti thread mandegake karo anyar lan terus nglakokaké tugas.

Mangkono, kita kudu nggunakake newSingleThreadExecutor karo blumbang siji-thread nalika kita arep kanggo proses tugas sequentially lan mung siji ing wektu, lan kita arep kanggo terus Processing tugas saka antrian preduli saka completion saka tugas sadurunge (eg kasus ngendi siji tugas kita mateni utas).

ThreadFactory

Nalika ngomong babagan nggawe lan nggawe ulang thread, kita ora bisa ngomongThreadFactory.

AThreadFactoryminangka obyek sing nggawe benang anyar sing dikarepake.

Kita bisa nggawe pabrik nggawe thread dhewe lan ngirim conto menyang Executors.newSingleThreadExecutor(ThreadFactory threadFactory) metode.


ExecutorService executorService = Executors.newSingleThreadExecutor(new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r, "MyThread");
            }
        });
                    
We override cara kanggo nggawe thread anyar, liwat jeneng thread kanggo konstruktor.

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;
            }
        });
                    
Kita ngganti jeneng lan prioritas thread digawe.

Supaya kita waca sing kita duwe 2 overloaded Executors.newSingleThreadExecutor cara. Siji tanpa paramèter, lan liya kanthi parameter ThreadFactory .

Nggunakake ThreadFactory , sampeyan bisa ngatur thread sing digawe kaya sing dibutuhake, contone, kanthi nyetel prioritas, nggunakake subclass thread, nambah UncaughtExceptionHandler menyang thread, lan liya-liyane.