Penjadwalan Pekerjaan Berbasis Prioritas di Jawa

1. Perkenalan

Dalam lingkungan multi-utas, terkadang kita perlu menjadwalkan tugas berdasarkan kriteria khusus, bukan hanya waktu pembuatan.

Mari kita lihat bagaimana kita bisa mencapai ini di Java - menggunakan PriorityBlockingQueue .

2. Ikhtisar

Katakanlah kita memiliki pekerjaan yang ingin kita jalankan berdasarkan prioritas 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 dan prioritas pekerjaan dalam metode run () .

Kami juga menambahkan sleep () sehingga kami mensimulasikan pekerjaan yang berjalan lebih lama; saat pekerjaan dijalankan, lebih banyak pekerjaan akan terkumpul dalam antrian prioritas.

Terakhir, JobPriority adalah enum sederhana:

public enum JobPriority { HIGH, MEDIUM, LOW }

3. Pembanding Kustom

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

Comparator.comparing(Job::getJobPriority);

4. Penjadwal Pekerjaan Prioritas

Dengan semua penyiapan selesai, sekarang mari kita terapkan penjadwal pekerjaan sederhana - yang menggunakan satu pelaksana utas untuk mencari pekerjaan di PriorityBlockingQueue dan menjalankannya:

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 sebuah instance dari PriorityBlockingQueue dari Job jenis dengan pembanding kustom. Pekerjaan selanjutnya yang akan dijalankan diambil dari antrian menggunakan metode take () yang mengambil dan menghapus kepala antrian.

Kode klien sekarang hanya perlu memanggil scheduleJob () - yang menambahkan pekerjaan ke antrian. The priorityQueue.add () antrian pekerjaan pada posisi yang tepat dibandingkan dengan pekerjaan yang ada dalam antrian, menggunakan JobExecutionComparator .

Perhatikan bahwa pekerjaan sebenarnya dijalankan menggunakan ExecutorService terpisah dengan kumpulan utas khusus.

5. Demo

Terakhir, inilah demonstrasi singkat penjadwal:

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 mendemonstrasikan bahwa pekerjaan dijalankan dalam urutan prioritas, kami telah mempertahankan POOL_SIZE sebagai 1 meskipun QUEUE_SIZE adalah 10. Kami menyediakan pekerjaan dengan berbagai prioritas ke penjadwal.

Berikut adalah contoh keluaran yang kami dapatkan untuk salah satu proses:

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

Outputnya dapat bervariasi di setiap proses. Namun, kita tidak boleh memiliki kasus di mana pekerjaan dengan prioritas lebih rendah dijalankan bahkan ketika antrian berisi pekerjaan dengan prioritas lebih tinggi.

6. Kesimpulan

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

Seperti biasa, file sumber dapat ditemukan di GitHub.