Az összetett rendszer egyik legnagyobb kihívása, hogy válaszképes maradjon a feladatok végrehajtása során. Ez a kihívás egy kiterjeszthető rendszerben nagyobb, ha az összetevők, amelyeket nem együttes futásra terveztek, ugyanazokat az erőforrásokat osztják meg. Az org.eclipse.core.runtime.jobs csomag megpróbálja megoldani ezt a problémát azáltal, hogy egy infrastruktúrát biztosít az egyidejűleg futó műveletek kezeléséhez. Ez az infrastruktúra a feladatok használatára épül, amely az aszinkron módon futtatható munkaegységet ábrázolja.
class TrivialJob extends Job { public TrivialJob() { super("Trivial Job"); } public IStatus run(IProgressMonitor monitor) { System.out.println("This is a job"); return Status.OK_STATUS; } }Az alábbi részletben létrehozásra és ütemezésre kerül egy feladat:
TrivialJob job = new TrivialJob(); System.out.println("About to schedule a job"); job.schedule(); System.out.println("Finished scheduling a job");A program kimenet időzítésfüggő. Azaz nem lehet meggyőződni arról, hogy a feladat run metódusa mikor kerül végrehajtásra a szállal kapcsolatban, amely létrehozta a feladatot és ütemezte ezt. A kimenet az alábbi lehet:
A feladat ütemezéséről Ez egy feladat Feladatütemezés befejezésevagy:
A feladat ütemezéséről Feladatütemezés befejezése Ez egy feladat
Ha folytatás előtt meg szeretne győződni arról, hogy a feladat befejeződött, akkor használhatja a join() metódust. Ez a metódus blokkolja a hívót addig, amíg a feladat be nem fejeződik, vagy a hívó szál megszakadásáig. Írjuk át a részletünket a fenti példa alapján determinisztikusabb módon:
TrivialJob job = new TrivialJob(); System.out.println("About to schedule a job"); job.schedule(); job.join(); if (job.getResult().isOk()) System.out.println("Job completed with success"); else System.out.println("Job did not complete successfully");Feltételezve, hogy a join() hívás nem kerül megszakításra, akkor ez a metódus garantáltan az alábbi eredményt adja vissza:
A feladat ütemezéséről Ez egy feladat Sikeresen befejeződött feladat
Általában nem hasznos a feladatot közvetlenül ütemezés után összefésülni, mivel ezáltal nem jön létre konkurencia. Ebben az esetben a feladat futtatás metódusának feladatát közvetlenül a meghívó szálban is elvégezheti. Később nézünk néhány példát, amelyben a join használatának több értelme van.
Az utolsó részlet szintén a feladat eredményét használja. Az eredmény az IStatus objektum, amelyet a feladat run() metódusa adja vissza. Ezen eredmény segítségével a szükséges objektumok visszaadhatók a feladat run metódusából. Az eredmény segítségével a hiba ( IStatus visszaadása IStatus.ERROR fontossággal) vagy törlés (IStatus.CANCEL) is jelezhető.
Láttuk, hogy hogyan ütemezhető egy feladat, hogyan várakozik a végrehajtásra, de számos egyéb érdekes dolog is van, amelyet a feladatokkal megtehet. Ha ütemez egy feladatot, de később úgy dönt, hogy már nincs rá szükség, akkor a cancel() metódus segítségével leállítható. Ha a törléskor a feladat még nem kezdte meg a futást, akkor a feladat azonnal eltávolításra kerül és nem fog futni. Ha a feladat már elkezdett futni, akkor a feladattól függ, hogy válaszolni akar-e a törlésre. Amikor egy feladatot próbál törölni, jól jön a join() metódus segítségével a rá várakozás. Az alábbiakban látható általános kifejezés a feladat törlésére szolgál, amely addig vár a folytatásra, amíg a feladat be nem fejeződik:
if (!job.cancel()) job.join();
Ha a törlés nem lép azonnal hatályba, akkor a cancel() hamis értéket ad vissza, és a hívó a join() metódussal megvárja, hogy a feladat sikeresen befejeződjön.
A törlésnél kevésbé drasztikus a sleep() metódus. Ha a feladat még nem kezdett el futni, akkor a metódus hatására a feladat felfüggesztésre kerül korlátlan időre. A feladatot a platform továbbra is megjegyzi, és a wakeUp() hívás hatására a feladat bekerül a várakozási sorba, amelyben egyszer majd végrehajtásra kerül.
A feladat számos állapoton megy át az élettartama során. Nem csak az alkalmazás programozási felületen keresztül kezelhető, mint a cancel() és sleep(), hanem az állapota is módosul a platform futásakor és a feladat végrehajtásakor. A feladatok az alábbi állapotokon mehetnek keresztül:
A feladat csak akkor tehető alvó állapotba, ha aktuálisan WAITING (várakozás) állapotban van. Egy alvó feladat felébresztéskor visszakerül WAITING állapotba. A feladat törlés hatására NONE állapotba kerül vissza.
Ha a bedolgozónak ismernie kell egy adott feladat állapotát, akkor bejegyezhet egy feladatmódosítás-figyelőt, amely értesítést kap arról, ahogy a feladat áthalad az életcikluson. Ez hasznos az előrehaladás megjelenítése vagy a feladat jelentésének elkészítéséhez.
A Feladat addJobChangeListener metódus egy figyelőt regisztrálhat egy adott feladaton. IJobChangeListener protokollt ad meg a feladat állapotváltozásainak reagálására:
Ezen esetekben a figyelő egy IJobChangeEvent elemmel kerül biztosításra, amely megadja, hogy a feladat állapotváltozáson megy át, és az állapotát befejezéskor (ha készen van).
Megjegyzés: A feladatok a getState() metódust is megadják a feladat aktuális állapotának lekéréséhez (viszonyítva). Ez az eredmény nem mindig megbízható, mivel a feladatok különböző szálban futnak, és az állapotuk változhat, mire a hívás visszatér. A feladatmódosítás-figyelő a javasolt mechanizmus a feladat állapotváltozásainak figyelésére.
IJobManager egy protokollt ad meg az összes feladat kezeléséhez a rendszerben. A bedolgozók, amely az előrehaladást jelenítik meg, vagy egyéb módon működnek együtt a feladatinfrastruktúrával, az IJobManager segítségével feladatokat hajhatnak végre, mint például a rendszer összes feladatának felfüggesztése, annak meghatározása, hogy mely feladat fut, vagy előrehaladás visszacsatolás fogadása az adott feladattól. A platform feladatkezelője a Platform API segítségével kérhető le:
IJobManager jobMan = Platform.getJobManager();
A bedolgozók, amelyeknek a rendszer összes feladatának állapotára szüksége van, bejegyezhetnek egy feladatmódosítás-figyelőt a feladatkezelőn ahelyett, hogy az egyedi feladatokon jegyeznék be őket.
Néha egyszerűbb, ha a bedolgozó a kapcsolódó feladatok csoportját egy egységként kezeli. Ez a feladatcsaládok segítségével hajtható végre. A feladat úgy adja meg, hogy egy adott családhoz tartozik, hogy felülríja a belongsTo metódust:
public static final String MY_FAMILY = "myJobFamily"; ... class FamilyJob extends Job { ... public boolean belongsTo(Object family) { return family == MY_FAMILY; } }IJobManager protokoll segítségével egy családba tartozó összes feladat törölhető, összefésülhető, alvó állapotba küldhető vagy kikereshető:
IJobManager jobMan = Platform.getJobManager(); jobMan.cancel(MY_FAMILY); jobMan.join(MY_FAMILY, null);
Mivel a feladatcsaládokat tetszőleges objektumok ábrázolják, az érdekes állapot tárolható magában az állapotcsaládban, és a feladatok szükség szerint dinamikusan összeépíthetnek családobjektumokat. Egyedi családobjektumokat kell használni a más bedolgozók által létrehozott családokkal esetleges interakció elkerülése érdekében.
A családok kialakítása a feladatcsoportok megkeresésének is kényelmes módja. Az IJobManager.find(Object family) metódus ki tudja keresni egy adott időben a futó, várakozó és alvó feladatok összes példányát.