Middle
Ako zorganizovať výmenu dát medzi dvoma vláknami v Jave?
sobes.tech AI
Odpoveď od AI
Spôsoby výmeny údajov medzi vláknami v Jave je možné organizovať nasledovne:
- Zdieľané premenné so synchronizáciou: Vlákna používajú zdieľané premenné, ku ktorým pristupujú synchronizovane pomocou kľúčového slova
synchronized, zámkov (Lockzjava.util.concurrent.locks) alebo atómových premenných (Atomiczjava.util.concurrent.atomic). - Dátové potrubia (Piped Streams): Prepojené vstupné/výstupné prúdy (
PipedInputStreamaPipedOutputStream) umožňujú jednému vláknu zapisovať údaje, zatiaľ čo iné ich číta.// Použitie Piped Streams try { PipedOutputStream pout = new PipedOutputStream(); PipedInputStream pin = new PipedInputStream(pout); // Vlákno 1: zápis new Thread(() -> { try { pout.write("Ahoj z vlákna 1".getBytes()); pout.close(); } catch (Exception e) { e.printStackTrace(); } }).start(); // Vlákno 2: čítanie 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(); } - Fronty (Queues): Použitie bezpečných kolekcií pre vlákna, ako je
BlockingQueue(napríklad,ArrayBlockingQueue,LinkedBlockingQueue), umožňuje jednému vláknu vkladať prvky do fronty, zatiaľ čo iné ich odoberá.import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; // Použitie BlockingQueue BlockingQueue<String> queue = new LinkedBlockingQueue<>(); // Výrobca new Thread(() -> { try { queue.put("Správa 1"); queue.put("Správa 2"); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }).start(); // Spotrebiteľ new Thread(() -> { try { System.out.println(queue.take()); System.out.println(queue.take()); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }).start(); - Mechanizmy
wait(),notify(),notifyAll(): Používajú sa na synchronizáciu vlákien na základe monitorov objektov. Jedno vlákno voláwait()na čakanie na podmienku, iné volánotify()alebonotifyAll()na oznámenie čakajúcim vláknam o zmene podmienky.// Použitie wait/notify class Data { private String message; private boolean empty = true; public synchronized String read() { while (empty) { try { wait(); // Čakanie na údaje } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } empty = true; notifyAll(); // Oznámenie o možnosti zápisu return message; } public synchronized void write(String message) { while (!empty) { try { wait(); // Čakanie, kým sa prečítajú predchádzajúce údaje } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } empty = false; this.message = message; notifyAll(); // Oznámenie o nových údajoch } } CompletableFuture: Umožňuje vytvárať asynchrónne výpočty a ich výsledky spájať, zabezpečujúc výmenu údajov prostredníctvom vracaných hodnôt a handlerov ukončenia.Exchanger: Umožňuje dvom vláknam vymeniť objekty v bode synchronizácie.
Výber konkrétnej metódy závisí od špecifiká úlohy, požadovanej úrovne synchronizácie, výkonu a zložitosti implementácie.