Introduksjon til Exchanger i Java

1. Oversikt

I denne opplæringen vil vi se på java.util.concurrent.Exchanger. Dette fungerer som et vanlig punkt for to tråder i Java for å utveksle objekter mellom dem.

2. Introduksjon til Exchanger

De Veksler klasse i Java kan brukes til å dele objekter mellom to tråder av typen T. Klassen gir bare en enkelt overbelastet metode bytte (T t).

Når påkalt Utveksling venter på at den andre tråden i paret også skal kalle den. På dette punktet finner den andre tråden den første tråden venter med objektet. Tråden bytter ut gjenstandene de holder og signaliserer sentralen, og nå kan de komme tilbake.

La oss se på et eksempel for å forstå meldingsutveksling mellom to tråder med Veksler:

@Test offentlig ugyldighet givenThreads_whenMessageExchanged_thenCorrect () {Exchanger exchanger = new Exchanger (); Kjørbar taskA = () -> {prøv {Strengmelding = exchanger.exchange ("fra A"); assertEquals ("fra B", melding); } fange (InterruptedException e) {Thread.currentThread.interrupt (); kaste nye RuntimeException (e); }}; Kjørbar oppgaveB = () -> {prøv {Strengmelding = veksler.exchange ("fra B"); assertEquals ("fra A", melding); } fange (InterruptedException e) {Thread.currentThread.interrupt (); kaste nye RuntimeException (e); }}; CompletableFuture.allOf (runAsync (taskA), runAsync (taskB)). Bli med (); }

Her har vi de to trådene som utveksler meldinger mellom hverandre ved hjelp av den vanlige veksleren. La oss se et eksempel der vi bytter et objekt fra hovedtråden med en ny tråd:

@Test offentlig ugyldighet givenThread_WhenExchangedMessage_thenCorrect () kaster InterruptedException {Exchanger exchanger = new Exchanger (); Runnable runner = () -> {try {String message = exchanger.exchange ("fra runner"); assertEquals ("til løper", melding); } fange (InterruptedException e) {Thread.currentThread.interrupt (); kaste nye RuntimeException (e); }}; CompletableFuture result = CompletableFuture.runAsync (runner); String msg = exchanger.exchange ("to runner"); assertEquals ("fra løper", msg); result.join (); }

Merk at vi må starte løper tråd først og senere samtale Utveksling() i hovedtråden.

Vær også oppmerksom på at den første trådens samtale kan ta en timeout hvis den andre tråden ikke når utvekslingspunktet i tide. Hvor lenge den første tråden skal vente, kan kontrolleres ved hjelp av overbelastet utveksling (T t, lang tidsavbrudd, TimeUnit timeUnit).

3. Ingen GC Data Exchange

Veksler kan brukes til å lage rørledningsmønstre med overføring av data fra en tråd til den andre. I denne delen oppretter vi en enkel stabel med tråder som kontinuerlig sender data mellom hverandre som en rørledning.

@Test offentlig ugyldighet gittData_whenPassedThrough_thenCorrect () kaster InterruptedException {Exchanger readerExchanger = ny Exchanger (); Veksler writerExchanger = ny Exchanger (); Kjørbar leser = () -> {KøleserBuffer = ny ConcurrentLinkedQueue (); while (true) {readerBuffer.add (UUID.randomUUID (). toString ()); hvis (readerBuffer.size ()> = BUFFER_SIZE) {readerBuffer = readerExchanger.exchange (readerBuffer); }}}; Kjørbar prosessor = () -> {KøprosessorBuffer = ny ConcurrentLinkedQueue (); KøforfatterBuffer = ny ConcurrentLinkedQueue (); processorBuffer = readerExchanger.exchange (processorBuffer); while (true) {writerBuffer.add (processorBuffer.poll ()); hvis (processorBuffer.isEmpty ()) {processorBuffer = readerExchanger.exchange (processorBuffer); writerBuffer = writerExchanger.exchange (writerBuffer); }}}; Kjørbar forfatter = () -> {KøforfatterBuffer = ny ConcurrentLinkedQueue (); writerBuffer = writerExchanger.exchange (writerBuffer); while (true) {System.out.println (writerBuffer.poll ()); hvis (writerBuffer.isEmpty ()) {writerBuffer = writerExchanger.exchange (writerBuffer); }}}; CompletableFuture.allOf (runAsync (leser), runAsync (prosessor), runAsync (skribent)). Bli med (); }

Her har vi tre tråder: leser, prosessor, og forfatter. Sammen jobber de som en enkelt rørledning som utveksler data mellom seg.

De readerExchanger deles mellom leser og prosessor tråden, mens writerExchanger deles mellom prosessor og forfatter tråd.

Merk at eksemplet her bare er for demonstrasjon. Vi må være forsiktige når vi lager uendelige løkker med mens (sant). Også for å holde koden lesbar har vi utelatt noen unntakshåndtering.

Dette mønsteret for utveksling av data mens bufferen brukes på nytt, gjør det mulig å samle mindre søppel. Byttemetoden returnerer de samme køforekomster, og det vil derfor ikke være noen GC for disse objektene. I motsetning til alle blokkeringskøer, lager ikke veksleren noen noder eller objekter for å holde og dele data.

Å lage en slik rørledning er lik Disrupter-mønsteret, med en nøkkelforskjell støtter Disrupter-mønsteret flere produsenter og forbrukere, mens en veksler kan brukes mellom et par forbrukere og produsenter.

4. Konklusjon

Så vi har lært hva Veksler er i Java, hvordan det fungerer, og vi har sett hvordan du bruker Veksler klasse. Vi opprettet også en rørledning og demonstrerte GC-mindre datautveksling mellom tråder.

Som alltid er koden tilgjengelig på GitHub.


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