Middle
Hoe organiseer je gegevensuitwisseling tussen twee threads in Java?
sobes.tech AI
Antwoord van AI
De gegevensuitwisseling tussen threads in Java kan op de volgende manieren worden georganiseerd:
- Gedeelde variabelen met synchronisatie: Threads gebruiken gedeelde variabelen, waarvan de toegang wordt gesynchroniseerd met behulp van het sleutelwoord
synchronized, vergrendelingen (Lockuitjava.util.concurrent.locks) of atomische variabelen (Atomicuitjava.util.concurrent.atomic). - Datastreams (Aangesloten streams): Verbonden invoer-/uitvoerstreams (
PipedInputStreamenPipedOutputStream) stellen één thread in staat gegevens te schrijven en een andere te lezen.// Gebruik van verbonden streams try { PipedOutputStream pout = new PipedOutputStream(); PipedInputStream pin = new PipedInputStream(pout); // Thread 1: schrijven new Thread(() -> { try { pout.write("Hallo van thread 1".getBytes()); pout.close(); } catch (Exception e) { e.printStackTrace(); } }).start(); // Thread 2: lezen new Thread(() -> { try { int data; while ((data = pin.read()) != -1) { System.out.print((char) data); } pin.close(); } catch (Exception e) { e.printStackTrace(); } }).start(); } catch (Exception e) { e.printStackTrace(); } - Wachtrijen (Queues): Het gebruik van thread-veilige collecties zoals
BlockingQueue(bijvoorbeeldArrayBlockingQueue,LinkedBlockingQueue) stelt één thread in staat elementen in de wachtrij te plaatsen en een andere ze te verwijderen.import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; // Gebruik van BlockingQueue BlockingQueue<String> queue = new LinkedBlockingQueue<>(); // Producent new Thread(() -> { try { queue.put("Bericht 1"); queue.put("Bericht 2"); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }).start(); // Consument new Thread(() -> { try { System.out.println(queue.take()); System.out.println(queue.take()); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }).start(); - Mechanismen
wait(),notify(),notifyAll(): Worden gebruikt om threads te synchroniseren op basis van objectmonitors. Een thread roeptwait()aan om te wachten op een voorwaarde, een andere roeptnotify()ofnotifyAll()aan om de wachtende threads te informeren over een verandering in de voorwaarde.// Gebruik van wait/notify class Data { private String message; private boolean empty = true; public synchronized String read() { while (empty) { try { wait(); // Wachten op gegevens } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } empty = true; notifyAll(); // Informeren dat schrijven mogelijk is return message; } public synchronized void write(String message) { while (!empty) { try { wait(); // Wachten tot de vorige gegevens zijn gelezen } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } empty = false; this.message = message; notifyAll(); // Informeren over nieuwe gegevens } } CompletableFuture: Maakt het mogelijk om asynchrone berekeningen te maken en deze te combineren, waarbij gegevens worden uitgewisseld via teruggekeerde waarden en voltooiingshandlers.Exchanger: Stelt twee threads in staat om objecten uit te wisselen op een synchronisatiepunt.
De keuze van een specifieke methode hangt af van de aard van de taak, het vereiste synchronisatieniveau, de prestaties en de complexiteit van de implementatie.