消费者线程未收到通知

时间:2015-11-15 18:30:49

标签: java multithreading thread-safety

我正在尝试实施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");
    }
}

0 个答案:

没有答案