Java 多线程代码中未通知工作线程

Java 多线程代码中未通知工作线程,java,multithreading,Java,Multithreading,我想用Java编写一个传统的生产者和消费者多线程程序。生产者线程将向线程安全列表发送消息,直到该列表已满。一旦缓冲区已满,它将通知工作线程,缓冲区将被清除。在我的编码中,不会通知工作线程 你知道原因吗?谢谢 package com; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.locks.Condition; import

我想用Java编写一个传统的生产者和消费者多线程程序。生产者线程将向线程安全列表发送消息,直到该列表已满。一旦缓冲区已满,它将通知工作线程,缓冲区将被清除。在我的编码中,不会通知工作线程

你知道原因吗?谢谢

package com;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadTest {

    public static void main(String[] args) {

        final List<String> bufferSafeList = Collections.synchronizedList(new ArrayList<String>());

        final ReentrantLock bufferLock = new ReentrantLock();
        final Condition bufferFull = bufferLock.newCondition();
      //  final Condition bufferEmpty = bufferLock.newCondition();

        Thread producerThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        bufferLock.lock();
                        bufferSafeList.add(System.currentTimeMillis() + "");
                        System.out.println("add to buffer " + bufferSafeList.size());
                        if (bufferSafeList.size() > 100) {
                            System.out.println("send wake up signal");
                            bufferFull.signalAll();

                            //waiting for buff cleared
                            while(!bufferSafeList.isEmpty()){
                                Thread.sleep(1000);
                            }                           
                        }

                         Thread.sleep(1000);
                    } catch(Exception e){
                        e.printStackTrace();
                    }
                    finally {
                        bufferLock.unlock();
                    }
                }
            }
        });
        producerThread.start();

        Thread workerThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        bufferLock.lock();
                        System.out.println("waiting for wakeup signal");
                        bufferFull.await();
                        System.out.println("clear buffer");

                        bufferSafeList.clear();                      
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    } finally {
                        bufferLock.unlock();
                    }
                }
            }
        });
        workerThread.start();
    }

}
package-com;
导入java.util.ArrayList;
导入java.util.Collections;
导入java.util.List;
导入java.util.concurrent.locks.Condition;
导入java.util.concurrent.locks.ReentrantLock;
公共类线程测试{
公共静态void main(字符串[]args){
final List bufferSafeList=Collections.synchronizedList(新的ArrayList());
final ReentrantLock bufferLock=新的ReentrantLock();
最终条件bufferFull=bufferLock.newCondition();
//最终条件bufferEmpty=bufferLock.newCondition();
Thread producerThread=新线程(new Runnable(){
@凌驾
公开募捐{
while(true){
试一试{
bufferLock.lock();
bufferSafeList.add(System.currentTimeMillis()+);
System.out.println(“添加到缓冲区”+bufferSafeList.size());
如果(bufferSafeList.size()>100){
System.out.println(“发送唤醒信号”);
bufferFull.signalAll();
//等待buff清除
而(!bufferSafeList.isEmpty()){
睡眠(1000);
}                           
}
睡眠(1000);
}捕获(例外e){
e、 printStackTrace();
}
最后{
bufferLock.unlock();
}
}
}
});
producerThread.start();
Thread workerThread=新线程(new Runnable(){
@凌驾
公开募捐{
while(true){
试一试{
bufferLock.lock();
System.out.println(“等待唤醒信号”);
bufferFull.wait();
System.out.println(“清除缓冲区”);
bufferSafeList.clear();
}捕获(例外情况除外){
例如printStackTrace();
}最后{
bufferLock.unlock();
}
}
}
});
workerThread.start();
}
}

在finally中,您只能
解锁
缓冲锁
,因此
workerThread
将永远无法取得比尝试获得


当缓冲区已满时,解锁
,以便
workerThread
可以继续运行如果生产者线程碰巧首先运行,这可能是因为它是首先启动的,它可能会首先锁定
bufferLock
,在这种情况下,它将填充列表并调用
bufferFull.signalAll()
消费者仍在等待获取锁时。然后,您忙着等待工作人员清除列表,但由于无法继续,它永远不会这样做

此外,即使在发出信号后解锁锁,也为时已晚。当工人等待条件时,信号已经来了又去。事实上,即使生产者等待获取锁直到它准备发出信号,也存在竞争条件


正确使用条件变量总是需要在等待前测试预期条件是否满足,如果从等待中恢复后条件不满足,则循环返回等待。通过实现这一点,您可以克服代码中的竞争。

我将解锁直接放在bufferFull.signalAll()之后;仍然不起作用。在发出信号之前,您需要
解锁
。您是否有正确使用条件变量的链接?@EdwardChen,在的说明部分如何?或者,这与使用所有
对象提供的较低级别
wait()
/
notify()
方法的常规模式非常相似,您肯定可以在没有帮助的情况下找到多个关于此的教程。这也不是严格意义上的Java。关于这个主题似乎信息量很大。