我正在尝试实施Producer / Consumer测试程序,以更好地理解低级别的线程。
这个想法是有一个共享资源,生产者用一些数据填充资源,并通知消费者数据可用,而消费者等待通知。
不幸的是,消费者线程永远不会醒来,因此等待不确定。
这是源代码:
public class ProducerConsumerTest {
private final Object lock = new Object();
private final static int N = 10;
/**
* The producer thread
*/
private class ProducerThread extends Thread {
private final Resource resource;
ProducerThread(Resource resource) {
this.resource = resource;
}
public void run() {
try {
for (int i = 0; i < N; i++) {
synchronized (lock) {
System.out.println("Put the resource " + i + " in the container");
resource.put(Integer.toString(i));
System.out.println("Notify the consumer");
lock.notifyAll();
System.out.println("Wait until it is consumed");
lock.wait();
}
}
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
}
}
/**
* The consumer thread
*/
private class ConsumerThread extends Thread {
private final Resource resource;
ConsumerThread(Resource resource) {
this.resource = resource;
}
public void run() {
try {
for (int i = 0; i < N; i++) {
synchronized (lock) {
System.out.println("Waiting for the resource " + i + " to arrive");
lock.wait();
String s = (String) resource.get();
System.out.println(s == null ? "<null>" : s + " ok!");
System.out.println("Notify the producer we are done.");
lock.notifyAll();
}
}
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
}
}
/**
* The main method
*/
public static void main(String argv[]) throws InterruptedException {
Resource<String> resource = new Resource<>();
ProducerThread producer = new ProducerConsumerTest().new ProducerThread(resource);
ConsumerThread consumer = new ProducerConsumerTest().new ConsumerThread(resource);
producer.start();
consumer.start();
}
}
和资源类:
public class Resource<T> {
private T resource;
public synchronized void put(T resource) {
this.resource = resource;
}
public synchronized T get() {
return resource;
}
}
这是输出:
Put the resource 0 in the container
Notify the consumer
Wait until it is consumed
Waiting for the resource 0 to arrive
在到达此版本的程序之前,我在调用IllegalMonitorStateException
时遇到了wait() or notify()
被抛出的问题。
经过一些研究后,我发现这种情况正在发生,因为当前线程并没有拥有对象监视器wait()
正在调用。
所以,有
synchronized(lock){
lock.notify();
lock.wait();
}
会修复异常的问题。
然后我认为共享2个线程之间的锁将允许管理执行。但是,正如您从输出中看到的那样,消费者线程会等待并且永远不会被唤醒。
感谢任何帮助。
编辑:
// Producer
public void run() {
try {
synchronized (lock) {
System.out.println("Put the resource " + 1 + " in the container");
resource.put(Integer.toString(1));
lock.notifyAll();
}
} catch (Exception e) {
System.out.println("InterruptedException caught");
}
}
// Consumer
public void run() {
try {
synchronized (lock) {
while (resource.get() == null) {
lock.wait();
}
String s = (String) resource.get();
System.out.println(s == null ? "<null>" : "Resource " + s + " arrived!");
resource.clear();
}
} catch (Exception e) {
System.out.println("InterruptedException caught");
}
}