Penjadualan Pekerjaan berdasarkan Keutamaan di Jawa

1. Pengenalan

Dalam persekitaran berbilang utas, kadang-kadang kita perlu menjadualkan tugas berdasarkan kriteria tersuai dan bukan hanya pada waktu pembuatan.

Mari lihat bagaimana kita dapat mencapainya di Java - menggunakan PriorityBlockingQueue .

2. Gambaran keseluruhan

Katakanlah kita mempunyai pekerjaan yang ingin kita laksanakan berdasarkan keutamaan mereka:

public class Job implements Runnable { private String jobName; private JobPriority jobPriority; @Override public void run() { System.out.println("Job:" + jobName + " Priority:" + jobPriority); Thread.sleep(1000); // to simulate actual execution time } // standard setters and getters }

Untuk tujuan demonstrasi, kami mencetak nama pekerjaan dan keutamaan dalam kaedah run () .

Kami juga menambah tidur () supaya kami mensimulasikan pekerjaan yang lebih lama; semasa pekerjaan dijalankan, lebih banyak pekerjaan akan terkumpul dalam barisan keutamaan.

Akhirnya, JobPriority adalah enum mudah:

public enum JobPriority { HIGH, MEDIUM, LOW }

3. Pembanding Khusus

Kita perlu menulis pembanding yang menentukan kriteria khusus kita; dan, di Java 8, itu remeh:

Comparator.comparing(Job::getJobPriority);

4. Penjadual Pekerjaan Keutamaan

Dengan semua penyediaan selesai, mari kita laksanakan penjadual kerja sederhana - yang menggunakan pelaksana utas tunggal untuk mencari pekerjaan di PriorityBlockingQueue dan melaksanakannya:

public class PriorityJobScheduler { private ExecutorService priorityJobPoolExecutor; private ExecutorService priorityJobScheduler = Executors.newSingleThreadExecutor(); private PriorityBlockingQueue priorityQueue; public PriorityJobScheduler(Integer poolSize, Integer queueSize) { priorityJobPoolExecutor = Executors.newFixedThreadPool(poolSize); priorityQueue = new PriorityBlockingQueue( queueSize, Comparator.comparing(Job::getJobPriority)); priorityJobScheduler.execute(() -> { while (true) { try { priorityJobPoolExecutor.execute(priorityQueue.take()); } catch (InterruptedException e) { // exception needs special handling break; } } }); } public void scheduleJob(Job job) { priorityQueue.add(job); } }

Kuncinya di sini adalah untuk membuat contoh jenis PriorityBlockingQueue of Job dengan pembanding tersuai. Tugas berikutnya untuk dilaksanakan dipilih dari barisan menggunakan kaedah take () yang mengambil dan membuang kepala antrian.

Kod pelanggan sekarang hanya perlu memanggil jadualJob () - yang menambahkan tugas ke dalam barisan. The priorityQueue.add () beratur kerja di kedudukan yang sesuai berbanding dengan pekerjaan yang sedia ada dalam barisan, menggunakan JobExecutionComparator .

Perhatikan bahawa pekerjaan sebenarnya dilaksanakan menggunakan ExecutorService yang terpisah dengan kumpulan utas khusus.

5. Demo

Akhirnya, inilah demonstrasi penjadual pantas:

private static int POOL_SIZE = 1; private static int QUEUE_SIZE = 10; @Test public void whenMultiplePriorityJobsQueued_thenHighestPriorityJobIsPicked() { Job job1 = new Job("Job1", JobPriority.LOW); Job job2 = new Job("Job2", JobPriority.MEDIUM); Job job3 = new Job("Job3", JobPriority.HIGH); Job job4 = new Job("Job4", JobPriority.MEDIUM); Job job5 = new Job("Job5", JobPriority.LOW); Job job6 = new Job("Job6", JobPriority.HIGH); PriorityJobScheduler pjs = new PriorityJobScheduler( POOL_SIZE, QUEUE_SIZE); pjs.scheduleJob(job1); pjs.scheduleJob(job2); pjs.scheduleJob(job3); pjs.scheduleJob(job4); pjs.scheduleJob(job5); pjs.scheduleJob(job6); // clean up }

Untuk menunjukkan bahawa tugas dijalankan mengikut urutan keutamaan, kami tetap menjadikan POOL_SIZE sebagai 1 walaupun QUEUE_SIZE adalah 10. Kami menyediakan pekerjaan dengan keutamaan yang berbeza-beza untuk penjadual.

Berikut adalah contoh output yang kami dapat untuk salah satu larian:

Job:Job3 Priority:HIGH Job:Job6 Priority:HIGH Job:Job4 Priority:MEDIUM Job:Job2 Priority:MEDIUM Job:Job1 Priority:LOW Job:Job5 Priority:LOW

Hasilnya boleh berbeza-beza sepanjang perjalanan. Namun, kita tidak seharusnya mempunyai kes di mana pekerjaan dengan keutamaan lebih rendah dijalankan walaupun barisan berisikan pekerjaan dengan keutamaan yang lebih tinggi.

6. Kesimpulannya

Dalam tutorial ringkas ini, kami melihat bagaimana PriorityBlockingQueue dapat digunakan untuk melaksanakan pekerjaan dalam urutan prioritas khusus.

Seperti biasa, fail sumber boleh didapati di GitHub.