Prioritetsbasert jobbplanlegging i Java

1. Introduksjon

I et miljø med flere tråder trenger vi noen ganger å planlegge oppgaver basert på tilpassede kriterier i stedet for bare opprettelsestiden.

La oss se hvordan vi kan oppnå dette i Java - ved hjelp av en PriorityBlockingQueue.

2. Oversikt

La oss si at vi har jobber vi vil utføre basert på deres prioritet:

public class Job implementerer Runnable {private String jobName; private JobPriority jobPriority; @Override public void run () {System.out.println ("Job:" + jobName + "Priority:" + jobPriority); Tråd. Søvn (1000); // for å simulere faktisk utføringstid} // standard setters og getters}

For demonstrasjonsformål skriver vi ut jobbnavnet og prioriteten i løpe() metode.

Vi la også til søvn() slik at vi simulerer en jobb som varer lenger; mens jobben utføres, vil flere jobber akkumuleres i prioritetskøen.

Endelig, JobPrioritet er en enkel enum:

offentlig enum JobPriority {HIGH, MEDIUM, LOW}

3. Tilpasset Komparator

Vi må skrive en komparator som definerer våre tilpassede kriterier; og i Java 8 er det trivielt:

Comparator.comparing (Job :: getJobPriority);

4. Prioritert jobbplanlegger

Når alt oppsettet er gjort, la oss nå implementere en enkel jobbplanlegger - som bruker en enkelt trådutfører for å lete etter jobber i PriorityBlockingQueue og henretter dem:

offentlig klasse PriorityJobScheduler {private ExecutorService prioritetJobPoolExecutor; private ExecutorService priorityJobScheduler = Executors.newSingleThreadExecutor (); privat PriorityBlockingQueue prioritetQueue; public PriorityJobScheduler (Integer poolSize, Integer queueSize) {priorityJobPoolExecutor = Executors.newFixedThreadPool (poolSize); priorityQueue = ny PriorityBlockingQueue (queueSize, Comparator.comparing (Job :: getJobPriority)); priorityJobScheduler.execute (() -> {while (true) {try {priorityJobPoolExecutor.execute (prioritetQueue.take ());} fangst (InterruptedException e) {// unntak trenger spesiell håndteringspause;}}}); } offentlig ugyldig planJob (Jobbjobb) {prioritetQueue.add (jobb); }}

Nøkkelen her er å lage en forekomst av PriorityBlockingQueue av Jobb skriv med en tilpasset komparator. Neste jobb som skal utføres plukkes fra køen ved hjelp av ta() metode som henter og fjerner hodet på køen.

Klientkoden trenger nå bare å ringe til scheduleJob () - som legger jobben til køen. De PriorityQueue.add () stiller jobben i kø på riktig plassering sammenlignet med eksisterende jobber i køen, ved hjelp av JobExecutionComparator.

Merk at de faktiske jobbene utføres ved hjelp av en separat ExecutorService med et dedikert trådbasseng.

5. Demo

Til slutt, her er en rask demonstrasjon av planleggeren:

privat statisk int POOL_SIZE = 1; privat statisk int QUEUE_SIZE = 10; @Test offentlig ugyldig nårMultiplePriorityJobsQueued_thenHighestPriorityJobIsPicked () {Job jobb1 = ny jobb ("Job1", JobPriority.LOW); Jobb jobb2 = ny jobb ("Job2", JobPriority.MEDIUM); Jobb3 = ny jobb ("Job3", JobPriority.HIGH); Jobb4 = ny jobb ("Job4", JobPriority.MEDIUM); Jobb jobb5 = ny jobb ("Job5", JobPriority.LOW); Jobb6 = ny jobb ("Job6", JobPriority.HIGH); PriorityJobScheduler pjs = ny PriorityJobScheduler (POOL_SIZE, QUEUE_SIZE); pjs.scheduleJob (jobb1); pjs.scheduleJob (jobb2); pjs.scheduleJob (jobb3); pjs.scheduleJob (jobb4); pjs.scheduleJob (jobb5); pjs.scheduleJob (jobb6); // rydde opp }

For å demonstrere at jobbene blir utført i prioritetsrekkefølgen, har vi beholdt POOL_SIZE som 1 selv om QUEUE_SIZE er 10. Vi tilbyr jobber med varierende prioritet til planleggeren.

Her er en prøveutgang vi fikk for en av kjøringen:

Jobb: Job3 Prioritet: HØY Job: Job6 Prioritet: HØY Job: Job4 Prioritet: MEDIUM Jobb: Job2 Prioritet: MEDIUM Job: Job1 Prioritet: LAV Jobb: Job5 Prioritet: LAV

Produksjonen kan variere mellom løp. Vi skal imidlertid aldri ha et tilfelle der en jobb med lavere prioritet utføres selv om køen inneholder en jobb med høyere prioritet.

6. Konklusjon

I denne raske opplæringen så vi hvordan PriorityBlockingQueue kan brukes til å utføre jobber i en tilpasset prioritetsrekkefølge.

Som vanlig kan kildefiler finnes på GitHub.


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