Raspored poslova zasnovan na prioritetu u Javi
1. Uvod
U okruženju s više niti, ponekad moramo rasporediti zadatke na temelju prilagođenih kriterija, umjesto samo na vremenu izrade.
Pogledajmo kako to možemo postići na Javi - pomoću a PriorityBlockingQueue.
2. Pregled
Recimo da imamo poslove koje želimo izvršavati na temelju njihovog prioriteta:
posao javne klase implementira Runnable {private String jobName; privatni JobPriority jobPriority; @Override public void run () {System.out.println ("Job:" + jobName + "Priority:" + jobPriority); Navoj.spavanje (1000); // za simulaciju stvarnog vremena izvršenja} // standardni postavljači i getteri}
U svrhu demonstracije ispisujemo naziv posla i prioritet u trčanje() metoda.
Također smo dodali spavati() tako da simuliramo posao koji traje duže; dok se posao izvršava, više poslova skupit će se u prioritetnom redu.
Konačno, Prioritet posla je jednostavan nabroj:
javni popis JobPriority {HIGH, MEDIUM, LOW}
3. Prilagođeno Usporednik
Moramo napisati usporedbu koja definira naše prilagođene kriterije; i u Javi 8 trivijalno:
Comparator.comparing (Job :: getJobPriority);
4. Planer prioriteta poslova
Nakon završetka postavljanja, implementirajmo jednostavan planer posla - koji zapošljava izvršitelja s jednom niti za traženje poslova u PriorityBlockingQueue i izvršava ih:
javna klasa PriorityJobScheduler {private ExecutorService priorityJobPoolExecutor; private ExecutorService prioritetJobScheduler = Izvršitelji.newSingleThreadExecutor (); private PriorityBlockingQueue priorityQueue; javni PriorityJobScheduler (Integer poolSize, Integer queueSize) {prioritetJobPoolExecutor = Izvršitelji.newFixedThreadPool (poolSize); priorityQueue = novi PriorityBlockingQueue (queueSize, Comparator.comparing (Job :: getJobPriority)); prioritetJobScheduler.execute (() -> {while (true) {try {priorityJobPoolExecutor.execute (prioritetQueue.take ());} catch (InterruptedException e) {// izuzetak treba posebnu pauzu rukovanja;}}}); } public void scheduleJob (posao posla) {prioritetQueue.add (posao); }}
Ključno je ovdje stvoriti instancu PriorityBlockingQueue od Posao tip s prilagođenim usporednikom. Sljedeći posao koji treba izvršiti odabire se iz reda pomoću uzeti() metoda koja dohvaća i uklanja glavu reda.
Klijentski kod sada jednostavno treba nazvati scheduleJob () - što dodaje posao u red čekanja. The prioritetQueue.add () postavlja posao na čekanje na odgovarajuću poziciju u odnosu na postojeće poslove u redu čekanja, koristeći JobExecutionComparator.
Imajte na umu da se stvarni poslovi izvršavaju pomoću zasebnog ExecutorService s namjenskim bazenom niti.
5. Demo
Na kraju, evo kratke demonstracije planera:
privatni statički int POOL_SIZE = 1; privatni statički int QUEUE_SIZE = 10; @Test public void whenMultiplePriorityJobsQueued_thenHighestPriorityJobIsPicked () {Job job1 = new Job ("Job1", JobPriority.LOW); Posao posao2 = novi posao ("Posao2", JobPriority.MEDIUM); Job job3 = novi posao ("Job3", JobPriority.HIGH); Posao posao4 = novi posao ("Job4", JobPriority.MEDIUM); Posao5 = novi posao ("Posao5", JobPriority.LOW); Job job6 = novi posao ("Job6", JobPriority.HIGH); PriorityJobScheduler pjs = novi PriorityJobScheduler (POOL_SIZE, QUEUE_SIZE); pjs.scheduleJob (posao1); pjs.scheduleJob (posao2); pjs.scheduleJob (posao3); pjs.scheduleJob (posao4); pjs.scheduleJob (posao5); pjs.scheduleJob (posao6); // počistiti }
Kako bismo demonstrirali da se poslovi izvršavaju prema redoslijedu prioriteta, zadržali smo VELIČINA BAZENA kao 1 iako je QUEUE_SIZE je 10. Planerima pružamo poslove s različitim prioritetom.
Evo primjera rezultata koji smo dobili za jedno od izvođenja:
Posao: Job3 Prioritet: HIGH Posao: Job6 Prioritet: HIGH Posao: Job4 Prioritet: SREDNJI Posao: Job2 Prioritet: SREDNJI Posao: Job1 Prioritet: LOW
Izlaz se može razlikovati u različitim izvedbama. Međutim, nikada ne bismo trebali imati slučaj kada se izvršava posao nižeg prioriteta, čak i ako red sadrži posao višeg prioriteta.
6. Zaključak
U ovom smo brzom vodiču vidjeli kako PriorityBlockingQueue može se koristiti za izvršavanje poslova prilagođenim redoslijedom prioriteta.
Kao i obično, izvorne datoteke mogu se naći na GitHubu.