Bevezetés a Java cserélőjébe

1. Áttekintés

Ebben az oktatóanyagban megvizsgáljuk java.util.concurrent.Exchanger. Ez a Java két szálának közös pontjaként működik, hogy objektumokat cseréljenek közöttük.

2. Bevezetés a cserélőbe

A Hőcserélő osztály a Java-ban használható az objektumok megosztására két típusú szál között T. Az osztály csak egyetlen túlterhelt módszert biztosít csere (T t).

Amikor felhívják csere várja, hogy a pár másik szála is felhívja. Ezen a ponton a második szál megtalálja az első szálat, amely a tárgyával várja. A szál kicseréli az általuk tartott tárgyakat, és jelzi a cserét, és most visszatérhetnek.

Nézzünk meg egy példát a két szál közötti üzenetcsere megértéséhez Hőcserélő:

@Test public void givenThreads_whenMessageExchanged_thenCorrect () {Cserélőcserélő = új Cserélő (); Futtatható feladatA = () -> {try {String message = exchangeer.exchange ("A-tól"); assertEquals ("B-től", üzenet); } catch (InterruptedException e) {Thread.currentThread.interrupt (); dobja új RuntimeException (e); }}; Futtatható feladatB = () -> {try {String message = exchangeer.exchange ("from B"); assertEquals ("A-tól", üzenet); } catch (InterruptedException e) {Thread.currentThread.interrupt (); dobja új RuntimeException (e); }}; CompletableFuture.allOf (runAsync (taskA), runAsync (taskB)). Join (); }

Itt van a két szál, amelyek üzeneteket cserélnek egymás között a közös váltó segítségével. Lássunk egy példát, ahol egy objektumot kicserélünk a fő szálból egy új szálra:

@Test public void givenThread_WhenExchangedMessage_thenCorrect () dobja az InterruptedException {Exchanger exchangeer = new Exchanger (); Futható futó = () -> {try {String message = exchangeer.exchange ("from runner"); assertEquals ("futónak", üzenet); } catch (InterruptedException e) {Thread.currentThread.interrupt (); dobja új RuntimeException (e); }}; CompletableFuture eredmény = CompletableFuture.runAsync (futó); String msg = exchangeer.exchange ("futónak"); assertEquals ("futótól", msg); eredmény.csatlakozzon (); }

Ne feledje, hogy el kell indítanunk a futó szál első és későbbi hívás csere() a fő szálban.

Vegye figyelembe azt is, hogy az első szál hívása időtúlléphet, ha a második szál nem éri el időben a cserepontot. Az első szál várakozási ideje a túlterheltek segítségével szabályozható csere (T t, hosszú időtúllépés, TimeUnit timeUnit).

3. Nincs GC adatcsere

Hőcserélő felhasználhatók csővezeték típusú minták létrehozására az adatok egyik szálról a másikra való továbbításával. Ebben a szakaszban létrehozunk egy egyszerű szál szálat, amely folyamatosan továbbítja az adatokat egymás között, mint csővezeték.

@Test public void givenData_whenPassedThrough_thenCorrect () dobja az InterruptedException {Exchanger readerExchanger = new Exchanger (); Hőcserélő writerExchanger = new Exchanger (); Futható olvasó = () -> {Queue readerBuffer = new ConcurrentLinkedQueue (); while (true) {olvasóBuffer.add (UUID.randomUUID (). toString ()); if (readerBuffer.size ()> = BUFFER_SIZE) {olvasóBuffer = readerExchanger.exchange (readerBuffer); }}}; Futható processzor = () -> {Queue processBuffer = új ConcurrentLinkedQueue (); Queue writerBuffer = new ConcurrentLinkedQueue (); processzorBuffer = readerExchanger.exchange (processzorBuffer); while (true) {íróBuffer.add (processzorBuffer.poll ()); if (processzorBuffer.isEmpty ()) {processBuffer = olvasóExchanger.exchange (processzorBuffer); íróBuffer = íróExchanger.exchange (íróBuffer); }}}; Futható író = () -> {Queue writerBuffer = new ConcurrentLinkedQueue (); íróBuffer = íróExchanger.exchange (íróBuffer); while (true) {System.out.println (íróBuffer.poll ()); if (íróBuffer.isEmpty ()) {íróBuffer = íróExchanger.exchange (íróBuffer); }}}; CompletableFuture.allOf (runAsync (olvasó), runAsync (processzor), runAsync (író)). Join (); }

Itt három szálunk van: olvasó, processzor, és író. Együtt dolgoznak egyetlen csővezetékként, amelyek adatcserét folytatnak közöttük.

A readerExchanger megoszlik a olvasó és a processzor szál, míg a íróVáltó megoszlik a processzor és a író cérna.

Vegye figyelembe, hogy az itt látható példa csak bemutató jellegű. Óvatosnak kell lennünk, miközben végtelen hurkokat hozunk létre míg (igaz). A kód olvashatósága érdekében kihagytunk néhány kivételt.

Ez az adatcsere mintázat a puffer újrafelhasználása közben lehetővé teszi a szemétgyűjtés kevesebbet. A csere metódus ugyanazokat a várakozási sorrend példányokat adja vissza, és ezért nem lennének GC ezek az objektumok. Bármely blokkoló várakozási sorral ellentétben a hőcserélő nem hoz létre csomópontokat vagy objektumokat adatok tárolására és megosztására.

Egy ilyen csővezeték létrehozása hasonló a megszakító mintához, kulcsfontosságú különbséggel a megszakító minta több gyártót és fogyasztót támogat, míg egy fogyasztó és termelő pár között cserélő lehetne.

4. Következtetés

Tehát megtanultuk, mit Hőcserélő Java-ban van, hogyan működik, és láttuk, hogyan kell használni a Hőcserélő osztály. Hoztunk létre egy folyamatot és bemutattuk a szálak közötti GC nélküli adatcserét.

Mint mindig, a kód elérhető a GitHubon.


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