Ütemezés Jakarta EE-ben

1. Áttekintés

Egy korábbi cikkünkben bemutattuk, hogyan kell ütemezni a feladatokat tavasszal@Ütemezettannotáció. Ebben a cikkben bemutatjuk, hogyan érhető el ugyanez a használatával az időzítő szolgáltatás egy Jakarta EE alkalmazásban az előző cikkben bemutatott minden esetre.

2. Engedélyezze az ütemezés támogatását

A Jakarta EE alkalmazásban nincs szükség az időzített feladatok támogatására. Az időzítő szolgáltatás egy konténer által kezelt szolgáltatás, amely lehetővé teszi az alkalmazások számára, hogy időalapú eseményekre ütemezett módszereket hívjanak meg. Például előfordulhat, hogy egy alkalmazásnak statisztikák létrehozása érdekében néhány jelentést kell futtatnia egy bizonyos órában.

Kétféle időzítő létezik:

  • Programozott időzítők: az időzítő szolgáltatás beilleszthető bármelyik babba (kivéve egy állapotos munkamenetet), és az üzleti logikát a @Időtúllépés. Az időzítő inicializálható egy annotált módszerrel @PostConstruct a babot, vagy inicializálható is csak egy módszer meghívásával.
  • Automatikus időzítők: az üzleti logikát a metódusok bármelyikével kiegészítik @Menetrend vagy @ Ütemezések. Ezek az időzítők inicializálódnak, amint az alkalmazás elindul.

Kezdjük tehát az első példánkkal.

3. A feladat ütemezése fix késéssel

Tavasszal ez egyszerűen a @Scheduled (fixDelay = 1000) annotáció. Ebben az esetben az utolsó végrehajtás vége és a következő végrehajtás kezdete közötti időtartam rögzített. A feladat mindig megvárja, amíg az előző befejeződik.

Pontosan ugyanezt a dolgot kell végrehajtani Jakartában. Az EE-t kissé nehezebb megvalósítani, mivel nincs hasonló beépített mechanizmus, ennek ellenére hasonló forgatókönyv megvalósítható egy kis extra kódolással. Nézzük meg, hogyan történik ez:

@Singleton public class FixedTimerBean {@EJB private WorkerBean workerBean; @Lock (LockType.READ) @Schedule (másodperc = "* / 5", perc = "*", óra = "*", tartós = hamis) public void atSchedule () dobja az InterruptedException {workerBean.doTimerWork (); }} 
@Singleton nyilvános osztály WorkerBean {private AtomicBoolean foglalt = new AtomicBoolean (hamis); A @Lock (LockType.READ) public void doTimerWork () dobja az InterruptedException {if (! Busy.compareAndSet (false, true)) {return; } próbáld ki a {Thread.sleep (20000L); } végül {foglalt.set (hamis); }}}

Mint látható, az időzítőt öt másodpercenként kell elindítani. Az esetünkben kiváltott módszer azonban 20 másodperces válaszidőt szimulált hívással alvás() az áramra cérna.

Ennek eredményeként a tároló továbbra is hívni fog doTimerWork () öt másodpercenként, de a módszer elején feltett feltétel, busy.compareAndSet (hamis, igaz), azonnal visszatér, ha az előző hívás nem fejeződött be. Ebben biztosítjuk, hogy a következő feladat csak az előző befejezése után kerüljön végrehajtásra.

4. A feladat ütemezése rögzített árfolyamon

Ennek egyik módja az időzítő szolgáltatás használata, amelyet a használatával injektálnak @Forrás és az annotált metódusban konfigurálta @PostConstruct. A módszerrel annotált @Időtúllépés az időzítő lejártakor hívjuk meg.

Amint az előző cikkben említettük, a feladat végrehajtásának kezdete nem várja meg az előző végrehajtás befejezését. Ezt az opciót akkor kell használni, ha a feladat minden végrehajtása független. A következő kódrészlet minden másodpercben elinduló időzítőt hoz létre:

@Startup @Singleton nyilvános osztály ProgrammaticAtFixedRateTimerBean {@Inject Event esemény; @ Resource TimerService timerService; @PostConstruct public void Initialize () {timerService.createTimer (0,1000, "Minden második időzítő késés nélkül"); } @Timeout public void programmicTimout (időzítő időzítő) {event.fire (új TimerEvent (timer.getInfo (). ToString ())); }}

Egy másik módszer a használat @Ütemezett annotáció. A következő kódrészletben öt másodpercenként időzítőt indítunk:

@Startup @Singleton public class ScheduleTimerBean {@Inject Event esemény; @Schedule (óra = "*", perc = "*", másodperc = "* / 5", info = "5 másodpercenként időzítő") public void automaticallyScheduled (Timer timer) {fireEvent (timer); } private void fireEvent (Timer timer) {event.fire (new TimerEvent (timer.getInfo (). toString ())); }}

5. Ütemezze a feladatot kezdeti késéssel

Ha a használati eset forgatókönyve megkívánja, hogy az időzítő késéssel induljon, akkor ezt is megtehetjük. Ebben az esetben a Jakarta EE engedélyezi az időzítő szolgáltatás használatát. Nézzünk meg egy példát, ahol az időzítő kezdeti késleltetése 10 másodperc, majd öt másodpercenként elindul:

@Startup @Singleton nyilvános osztály ProgrammaticWithInitialFixedDelayTimerBean {@Inject Event esemény; @ Resource TimerService timerService; @PostConstruct public void Initialize () {timerService.createTimer (10000, 5000, "Késleltessen 10 másodpercet, majd 5 másodpercenként időzítőt"); } @Timeout public void programmicTimout (Timer timer) {event.fire (new TimerEvent (timer.getInfo (). ToString ())); }}

A createTimer a mintánkban alkalmazott módszer a következő aláírást használja createTimer (hosszú kezdőDuration, hosszú intervalDuration, java.io.Serializálható információk) hol kezdeti időtartam a milliszekundumok száma, amelynek el kell telnie az első időzítő lejárati értesítése előtt, és intervalDuration az ezredmásodpercek száma, amelynek el kell telnie az időzítő lejárati értesítései között.

Ebben a példában egy kezdeti időtartam 10 másodperc és an intervalDuration öt másodpercig. A feladatot a. Után először hajtják végre kezdeti időtartam értéket, és a továbbiakban is a intervalDuration.

6. A feladat ütemezése a Cron kifejezések használatával

Az összes ütemező, amelyet láttunk, mind programozott, mind automatikus, lehetővé teszi a cron kifejezések használatát. Lássunk egy példát:

@Schedules ({@Schedule (dayOfMonth = "Utolsó"), @Schedule (dayOfWeek = "Péntek, hour =" 23 ")}) public void doPeriodicCleanup () {...}

Ebben a példában a módszer doPeriodicCleanup () minden pénteken 23: 00-kor és a hónap utolsó napján hívják.

7. Következtetés

Ebben a cikkben különféle módokat kerestünk ütemezze a feladatokat a Jakarta EE környezetben kiindulási alapként egy korábbi cikket, ahol a mintákat a Spring alkalmazásával készítettük.

A kódminták a GitHub tárházban találhatók.