Op prioriteit gebaseerde taakplanning in Java

1. Inleiding

In een omgeving met meerdere threads moeten we soms taken plannen op basis van aangepaste criteria in plaats van alleen de aanmaaktijd.

Laten we eens kijken hoe we dit in Java kunnen bereiken - met behulp van een PriorityBlockingQueue.

2. Overzicht

Laten we zeggen dat we banen hebben die we willen uitvoeren op basis van hun prioriteit:

public class Job implementeert Runnable {private String jobName; privé JobPriority jobPriority; @Override public void run () {System.out.println ("Job:" + jobName + "Priority:" + jobPriority); Thread.sleep (1000); // om de werkelijke uitvoeringstijd te simuleren} // standaard setters en getters}

Voor demonstratiedoeleinden printen we de taaknaam en prioriteit in het rennen() methode.

We hebben ook toegevoegd slaap() zodat we een langer lopende baan simuleren; terwijl de taak wordt uitgevoerd, zullen er meer taken worden verzameld in de prioriteitswachtrij.

Tenslotte, JobPriority is een simpele opsomming:

openbare opsomming JobPriority {HIGH, MEDIUM, LOW}

3. Aangepast Comparator

We moeten een vergelijker schrijven die onze aangepaste criteria definieert; en in Java 8 is het triviaal:

Comparator.comparing (Job :: getJobPriority);

4. Prioritaire taakplanner

Nu alle instellingen zijn voltooid, gaan we nu een eenvoudige taakplanner implementeren - die een enkele thread-uitvoerder gebruikt om naar taken in de PriorityBlockingQueue en voert ze uit:

openbare klasse PriorityJobScheduler {privé ExecutorService priorityJobPoolExecutor; private ExecutorService priorityJobScheduler = Executors.newSingleThreadExecutor (); privé PriorityBlockingQueue priorityQueue; openbare PriorityJobScheduler (geheel getal poolSize, geheel getal queueSize) {priorityJobPoolExecutor = Executors.newFixedThreadPool (poolSize); priorityQueue = nieuwe PriorityBlockingQueue (queueSize, Comparator.comparing (Job :: getJobPriority)); priorityJobScheduler.execute (() -> {while (true) {probeer {priorityJobPoolExecutor.execute (priorityQueue.take ());} catch (InterruptedException e) {// uitzondering heeft speciale afhandeling nodig;}}}); } public void scheduleJob (Job job) {priorityQueue.add (job); }}

De sleutel hier is om een ​​instantie van PriorityBlockingQueue van Job typ met een aangepaste comparator. De volgende taak die moet worden uitgevoerd, wordt uit de wachtrij gekozen met nemen() methode die de kop van de wachtrij ophaalt en verwijdert.

De klantcode hoeft nu alleen maar het scheduleJob () - waardoor de taak aan de wachtrij wordt toegevoegd. De prioriteitQueue.add () zet de taak op de juiste positie in de wachtrij in vergelijking met bestaande taken in de wachtrij, met behulp van de JobExecutionComparator.

Merk op dat de feitelijke taken worden uitgevoerd met behulp van een aparte ExecutorService met een speciale threadpool.

5. Demo

Eindelijk, hier is een korte demonstratie van de planner:

privé statische int POOL_SIZE = 1; privé statische int QUEUE_SIZE = 10; @Test openbaar ongeldig whenMultiplePriorityJobsQueued_thenHighestPriorityJobIsPicked () {Job job1 = nieuwe job ("Job1", JobPriority.LOW); Job job2 = nieuwe job ("Job2", JobPriority.MEDIUM); Job job3 = nieuwe job ("Job3", JobPriority.HIGH); Job job4 = nieuwe job ("Job4", JobPriority.MEDIUM); Job job5 = nieuwe job ("Job5", JobPriority.LOW); Job job6 = nieuwe job ("Job6", JobPriority.HIGH); PriorityJobScheduler pjs = nieuwe PriorityJobScheduler (POOL_SIZE, QUEUE_SIZE); pjs.scheduleJob (job1); pjs.scheduleJob (job2); pjs.scheduleJob (job3); pjs.scheduleJob (job4); pjs.scheduleJob (job5); pjs.scheduleJob (job6); // schoonmaken }

Om te demonstreren dat de taken worden uitgevoerd in de volgorde van prioriteit, hebben we de ZWEMBAD GROOTTE als 1, hoewel de QUEUE_SIZE is 10. Wij bieden jobs met wisselende prioriteit aan de planner.

Hier is een voorbeelduitvoer die we hebben gekregen voor een van de runs:

Job: Job3 Prioriteit: HOOG Job: Job6 Prioriteit: HOOG Job: Job4 Prioriteit: MEDIUM Job: Job2 Prioriteit: MEDIUM Job: Job1 Prioriteit: LOW Job: Job5 Prioriteit: LAAG

De output kan variëren tussen runs. We zouden echter nooit een geval moeten hebben waarin een taak met een lagere prioriteit wordt uitgevoerd, zelfs als de wachtrij een taak met een hogere prioriteit bevat.

6. Conclusie

In deze korte tutorial hebben we gezien hoe PriorityBlockingQueue kan worden gebruikt om taken uit te voeren in een aangepaste prioriteitsvolgorde.

Zoals gewoonlijk zijn bronbestanden te vinden op GitHub.


$config[zx-auto] not found$config[zx-overlay] not found