23:45
Урок 27: Обмен данными между потоками

Курс по программированию на Java

Урок 27: Обмен данными между потоками

Обмен данными между потоками — это важный аспект многопоточного программирования. В Java для этой цели используются различные механизмы, такие как wait(), notify(), notifyAll(), а также высокоуровневые структуры данных, такие как BlockingQueue. Эти механизмы позволяют потокам безопасно передавать данные и синхронизировать своё выполнение.

Использование wait() и notify()

Методы wait(), notify() и notifyAll() позволяют потокам взаимодействовать друг с другом, ожидая выполнения определённых условий. Рассмотрим пример использования этих методов:

class Data {
 private String packet;

 // Метод синхронизирован для безопасного доступа из разных потоков
 public synchronized void send(String packet) {
 this.packet = packet;
 notify();
 }

 public synchronized String receive() throws InterruptedException {
 wait();
 return packet;
 }
}

public class WaitNotifyExample {
 public static void main(String[] args) {
 Data data = new Data();

 Thread sender = new Thread(() -> {
 data.send("Привет, мир!");
 });

 Thread receiver = new Thread(() -> {
 try {
 String receivedMessage = data.receive();
 System.out.println("Получено сообщение: " + receivedMessage);
 } catch (InterruptedException e) {
 Thread.currentThread().interrupt();
 }
 });

 receiver.start();
 sender.start();
 }
}

Результат выполнения

Получено сообщение: Привет, мир!

Использование BlockingQueue

BlockingQueue — это очередь с блокировкой, которая позволяет потокам безопасно обмениваться данными, автоматически управляя блокировками и уведомлениями. Пример использования BlockingQueue:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class BlockingQueueExample {
 public static void main(String[] args) {
 BlockingQueue queue = new ArrayBlockingQueue<>(10);

 Thread producer = new Thread(() -> {
 try {
 queue.put("Привет, мир!");
 System.out.println("Сообщение отправлено");
 } catch (InterruptedException e) {
 Thread.currentThread().interrupt();
 }
 });

 Thread consumer = new Thread(() -> {
 try {
 String message = queue.take();
 System.out.println("Получено сообщение: " + message);
 } catch (InterruptedException e) {
 Thread.currentThread().interrupt();
 }
 });

 producer.start();
 consumer.start();
 }
}

Результат выполнения

Сообщение отправлено
Получено сообщение: Привет, мир!

Упражнения

Упражнение 1: Использование wait() и notify()

Напишите программу, в которой один поток генерирует числа от 1 до 5, а другой поток их выводит. Используйте методы wait() и notify() для координации работы потоков.

Решение:

class NumberGenerator {
 private int number;
 private boolean ready = false;

 public synchronized void generate() throws InterruptedException {
 for (int i = 1; i <= 5; i++) {
 while (ready) {
 wait();
 }
 number = i;
 ready = true;
 notify();
 }
 }

 public synchronized void print() throws InterruptedException {
 for (int i = 1; i <= 5; i++) {
 while (!ready) {
 wait();
 }
 System.out.println("Сгенерировано число: " + number);
 ready = false;
 notify();
 }
 }
}

public class NumberGeneratorExample {
 public static void main(String[] args) {
 NumberGenerator generator = new NumberGenerator();

 Thread generatorThread = new Thread(() -> {
 try {
 generator.generate();
 } catch (InterruptedException e) {
 Thread.currentThread().interrupt();
 }
 });

 Thread printerThread = new Thread(() -> {
 try {
 generator.print();
 } catch (InterruptedException e) {
 Thread.currentThread().interrupt();
 }
 });

 generatorThread.start();
 printerThread.start();
 }
}

Объяснение: Программа создает два потока: один генерирует числа от 1 до 5, а другой их выводит. Для координации работы потоков используются методы wait() и notify().

Упражнение 2: Использование BlockingQueue

Напишите программу, которая создает очередь и два потока: один поток добавляет элементы в очередь, а другой извлекает их. Используйте BlockingQueue для обмена данными между потоками.

Решение:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class BlockingQueueExample {
 public static void main(String[] args) {
 BlockingQueue queue = new ArrayBlockingQueue<>(5);

 Thread producer = new Thread(() -> {
 try {
 for (int i = 1; i <= 5; i++) {
 queue.put(i);
 System.out.println("Добавлено: " + i);
 }
 } catch (InterruptedException e) {
 Thread.currentThread().interrupt();
 }
 });

 Thread consumer = new Thread(() -> {
 try {
 for (int i = 1; i <= 5; i++) {
 int value = queue.take();
 System.out.println("Извлечено: " + value);
 }
 } catch (InterruptedException e) {
 Thread.currentThread().interrupt();
 }
 });

 producer.start();
 consumer.start();
 }
}

Объяснение: Программа создает очередь и два потока: один поток добавляет числа в очередь, а другой их извлекает. Для обмена данными между потоками используется BlockingQueue, которая автоматически управляет блокировками и уведомлениями.

Категория: Java | Просмотров: 36 | Добавил: Admin | Рейтинг: 0.0/0
Всего комментариев: 0
Имя *:
Email *:
Код *: