Middle
Πώς μπορεί να οργανωθεί η ανταλλαγή δεδομένων μεταξύ δύο νημάτων σε Java;
sobes.tech AI
Απάντηση από AI
Οι τρόποι ανταλλαγής δεδομένων μεταξύ νημάτων στη Java μπορούν να οργανωθούν με τους ακόλουθους τρόπους:
- Κοινές μεταβλητές με συγχρονισμό: Τα νήματα χρησιμοποιούν κοινές μεταβλητές, στις οποίες η πρόσβαση συγχρονίζεται με τη λέξη-κλειδί
synchronized, μπλοκ (Lockαπόjava.util.concurrent.locks) ή ατομικές μεταβλητές (Atomicαπόjava.util.concurrent.atomic). - Διαδρομές δεδομένων (Piped Streams): Συνδεδεμένες ροές εισόδου/εξόδου (
PipedInputStreamκαιPipedOutputStream) επιτρέπουν σε μια ροή να γράφει δεδομένα, ενώ μια άλλη να τα διαβάζει.// Χρήση Piped Streams try { PipedOutputStream pout = new PipedOutputStream(); PipedInputStream pin = new PipedInputStream(pout); // Ροή 1: εγγραφή new Thread(() -> { try { pout.write("Γειά σου από το νήμα 1".getBytes()); pout.close(); } catch (Exception e) { e.printStackTrace(); } }).start(); // Ροή 2: ανάγνωση 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): Η χρήση ασφαλών για νήματα συλλογών, όπως το
BlockingQueue(π.χ.,ArrayBlockingQueue,LinkedBlockingQueue), επιτρέπει σε ένα νήμα να τοποθετεί στοιχεία στην ουρά, και σε ένα άλλο να τα εξάγει.import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; // Χρήση BlockingQueue BlockingQueue<String> queue = new LinkedBlockingQueue<>(); // Παραγωγός new Thread(() -> { try { queue.put("Μήνυμα 1"); queue.put("Μήνυμα 2"); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }).start(); // Καταναλωτής new Thread(() -> { try { System.out.println(queue.take()); System.out.println(queue.take()); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }).start(); - Μηχανισμοί
wait(),notify(),notifyAll(): Χρησιμοποιούνται για συγχρονισμό νημάτων με βάση τους παρατηρητές αντικειμένων. Ένα νήμα καλείwait()για να περιμένει μια συνθήκη, ενώ ένα άλλο καλείnotify()ήnotifyAll()για να ειδοποιήσει τα αναμένοντα νήματα για την αλλαγή της συνθήκης.// Χρήση wait/notify class Data { private String message; private boolean empty = true; public synchronized String read() { while (empty) { try { wait(); // Περιμένουμε δεδομένα } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } empty = true; notifyAll(); // Ειδοποιούμε για δυνατότητα εγγραφής return message; } public synchronized void write(String message) { while (!empty) { try { wait(); // Περιμένουμε μέχρι να διαβαστούν τα προηγούμενα δεδομένα } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } empty = false; this.message = message; notifyAll(); // Ειδοποιούμε για νέα δεδομένα } } CompletableFuture: Επιτρέπει τη δημιουργία ασύγχρονων υπολογισμών και τον συνδυασμό των αποτελεσμάτων τους, διασφαλίζοντας ανταλλαγή δεδομένων μέσω των επιστρεφόμενων τιμών και των χειριστών ολοκλήρωσης.Exchanger: Επιτρέπει σε δύο νήματα να ανταλλάσσουν αντικείμενα σε σημείο συγχρονισμού.
Η επιλογή συγκεκριμένης μεθόδου εξαρτάται από τη φύση της εργασίας, το απαιτούμενο επίπεδο συγχρονισμού, την απόδοση και την πολυπλοκότητα υλοποίησης.