Middle
Wie kann man den Datenaustausch zwischen zwei Threads in Java organisieren?
sobes.tech KI
Antwort von AI
Der Datenaustausch zwischen Threads in Java kann auf folgende Weisen organisiert werden:
- Gemeinsame Variablen mit Synchronisation: Threads verwenden gemeinsame Variablen, auf die mit dem Schlüsselwort
synchronized, Sperren (Lockausjava.util.concurrent.locks) oder atomaren Variablen (Atomicausjava.util.concurrent.atomic) zugegriffen wird. - Datenpipelines (Verkettete Streams): Verbundene Ein- und Ausgabeströme (
PipedInputStreamundPipedOutputStream) ermöglichen es einem Thread, Daten zu schreiben, und einem anderen, sie zu lesen.// Verwendung von piped streams try { PipedOutputStream pout = new PipedOutputStream(); PipedInputStream pin = new PipedInputStream(pout); // Thread 1: Schreiben new Thread(() -> { try { pout.write("Hallo vom Thread 1".getBytes()); pout.close(); } catch (Exception e) { e.printStackTrace(); } }).start(); // Thread 2: Lesen 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(); } - Queues: Die Verwendung von thread-sicheren Sammlungen wie
BlockingQueue(z.B.ArrayBlockingQueue,LinkedBlockingQueue) ermöglicht es einem Thread, Elemente in die Warteschlange zu legen, und einem anderen, sie zu entnehmen.import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; // Verwendung von BlockingQueue BlockingQueue<String> queue = new LinkedBlockingQueue<>(); // Hersteller new Thread(() -> { try { queue.put("Nachricht 1"); queue.put("Nachricht 2"); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }).start(); // Verbraucher new Thread(() -> { try { System.out.println(queue.take()); System.out.println(queue.take()); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }).start(); - Mechanismen
wait(),notify(),notifyAll(): Werden verwendet, um Threads anhand von Objektmonitoren zu synchronisieren. Ein Thread ruftwait()auf, um auf eine Bedingung zu warten, ein anderer ruftnotify()odernotifyAll()auf, um wartende Threads über eine Änderung der Bedingung zu benachrichtigen.// Verwendung von wait/notify class Data { private String message; private boolean empty = true; public synchronized String read() { while (empty) { try { wait(); // Warten auf Daten } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } empty = true; notifyAll(); // Benachrichtigen, dass Schreiben möglich ist return message; } public synchronized void write(String message) { while (!empty) { try { wait(); // Warten, bis die vorherigen Daten gelesen werden } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } empty = false; this.message = message; notifyAll(); // Benachrichtigung über neue Daten } } CompletableFuture: Ermöglicht das Erstellen asynchroner Berechnungen und deren Kombination, wobei Daten durch Rückgabewerte und Abschluss-Handler ausgetauscht werden.Exchanger: Ermöglicht es zwei Threads, Objekte an einem Synchronisationspunkt auszutauschen.
Die Wahl einer bestimmten Methode hängt von der Art der Aufgabe, dem erforderlichen Synchronisationsgrad, der Leistung und der Komplexität der Implementierung ab.