Проблема производителя-потребителя — это классическая проблема синхронизации в информатике. Он включает в себя два типа потоков, известных как производители и потребители, которые используют общий ресурс, обычно буфер. Производители генерируют данные и добавляют их в буфер, а потребители извлекают и обрабатывают данные из буфера. Цель состоит в том, чтобы гарантировать, что производители и потребители могут работать одновременно без каких-либо конфликтов или повреждения данных.
Существует несколько методов реализации задачи производитель-потребитель. Вот несколько распространенных подходов и примеры кода:
Метод 1: использование синхронизированных методов/блокировок
import java.util.LinkedList;
class Buffer {
private LinkedList<Integer> buffer = new LinkedList<>();
private int capacity;
public Buffer(int capacity) {
this.capacity = capacity;
}
public synchronized void produce(int item) throws InterruptedException {
while (buffer.size() == capacity) {
wait();
}
buffer.add(item);
notifyAll();
}
public synchronized int consume() throws InterruptedException {
while (buffer.isEmpty()) {
wait();
}
int item = buffer.remove();
notifyAll();
return item;
}
}
class Producer implements Runnable {
private Buffer buffer;
public Producer(Buffer buffer) {
this.buffer = buffer;
}
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
buffer.produce(i);
System.out.println("Produced: " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Consumer implements Runnable {
private Buffer buffer;
public Consumer(Buffer buffer) {
this.buffer = buffer;
}
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
int item = buffer.consume();
System.out.println("Consumed: " + item);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Main {
public static void main(String[] args) {
Buffer buffer = new Buffer(5);
Thread producerThread = new Thread(new Producer(buffer));
Thread consumerThread = new Thread(new Consumer(buffer));
producerThread.start();
consumerThread.start();
}
}
Метод 2: использование BlockingQueue
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
class Producer implements Runnable {
private BlockingQueue<Integer> buffer;
public Producer(BlockingQueue<Integer> buffer) {
this.buffer = buffer;
}
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
buffer.put(i);
System.out.println("Produced: " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Consumer implements Runnable {
private BlockingQueue<Integer> buffer;
public Consumer(BlockingQueue<Integer> buffer) {
this.buffer = buffer;
}
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
int item = buffer.take();
System.out.println("Consumed: " + item);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Main {
public static void main(String[] args) {
BlockingQueue<Integer> buffer = new LinkedBlockingQueue<>(5);
Thread producerThread = new Thread(new Producer(buffer));
Thread consumerThread = new Thread(new Consumer(buffer));
producerThread.start();
consumerThread.start();
}
}
Это всего лишь два примера того, как реализовать проблему производитель-потребитель в Java. Существуют и другие варианты и методы в зависимости от языка программирования и платформы параллелизма, которую вы используете.