자바에서는 아래 코드를 사용하여 간단한 대기 및 notifyAll() 메서드를 사용하여 생성자 및 소비자 구현을 작성하려고했습니다. 몇 초 동안 실행되고 나중에 중단됩니다. 모든 문제를 해결하는 방법.생산자 소비자의 교착 상태를 해결하는 방법
import java.util.ArrayDeque;
import java.util.Queue;
public class Prod_consumer {
static Queue<String> q = new ArrayDeque(10);
static class Producer implements Runnable {
public void run() {
while (true) {
if (q.size() == 10) {
synchronized (q) {
try {
System.out.println("Q is full so waiting");
q.wait();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
synchronized (q) {
String st = System.currentTimeMillis() + "";
q.add(st);
q.notifyAll();
}
}
}
}
static class Consumer implements Runnable {
public void run() {
while (true) {
if (q.isEmpty()) {
synchronized(q) {
try {
System.out.println("Q is empty so waiting ");
q.wait();
}catch(InterruptedException ie) {
ie.printStackTrace();
}
}
}
synchronized(q) {
System.out.println(q.remove());
q.notifyAll();
}
}
}
}
public static void main(String args[]) {
Thread consumer = new Thread(new Consumer());
Thread consumer2 = new Thread(new Consumer());
Thread producer = new Thread(new Producer());
producer.start();
consumer.start();
consumer2.start();
}
}
하나 사소한 문제는 내가 제기하고자합니다. 일반적으로 스레드가 대기 상태가되면, 누군가가 알릴 때까지 획득 한 해당 모니터를 포기합니다. wait()에서 깨어 나면 스레드는 이미 모니터를 획득하게됩니다. 그러나 당신의 접근 방식은 (싱크 블록을 떠나서) 획득 한 모니터를 포기하고, 여전히 (내가 인식 할 수있는 것에서 작동하지만) 여분의 불필요한 부담을 가중시키는 다시 획득합니다. –
@AdrianShum - 문제를 적어두면 좋습니다. 생산자 스레드 또는 소비자 스레드가 여러 개인 경우'synchronized' 블록을 남겨두면 각각의 큐에 약간의 큐를 사용할 기회가 주어집니다. 'while' 블록이'synchronized' 블록 안에 있다면, 일단 생산자 나 소비자가 모니터를 얻으면 대기열이 용량에 있거나 비어있을 때까지 기다리게됩니다 (해당되는 경우). 이것이 원하는 동작이면 중첩 순서를 뒤집는 것이 적절할 것입니다. –
심지어 루프를 sync 블록으로 이동해도 대기열이 비어 있거나 비울 때까지 모니터를 유지하지 않습니다. 일단 wait()로 이동하면 모니터가 해제되고 다른 스레드는 여전히 "대기열 사용"이 가능합니다. 유일한 차이점은 모니터를 해제하고 다시 가져 오는 오버 헤드입니다. –