Konkurencia-infrastruktúra

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.

Feladatok

A Job osztály a más feladatokkal együtt futó aszinkron munka egységét ábrázolja. A feladat végrehajtásához a bedolgozó létrehoz egy feladatot, majd ütemezi ezt. A feladat ütemezéskor hozzáadódik a platform által kezelt feladatsorhoz. A platform egy háttér ütemezési szálat használ az összes függőben lévő feladat kezeléséhez. Ha a futó feladat befejeződik, akkor eltávolításra kerül a sorból, és a platform eldönti, hogy melyik feladat fusson következőnek. A feladat aktívvá válásakor a platform meghívja a run() metódust. A feladatok a legjobban egy egyszerű példával szemlétethetők:
   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ése
vagy:
   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ő.

Általános feladatműveletek

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.

Feladatállapotok

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.

Feladatmódosítás-figyelők

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.

A feladatkezelő

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.

Feladatcsaládok

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.