我有两个线程,我正在使用同步块内的Object的notify()和wait()方法进行锁定。我想确保主线程永远不会被阻塞,所以我用这种方式使用布尔值(只提供相关代码。)
//Just to explain an example queue
private Queue<CustomClass> queue = new Queue();
//this is the BOOLEAN
private boolean isRunning = false;
private Object lock;
public void doTask(){
ExecutorService service = Executors.newCachedThreadPool();
//the invocation of the second thread!!
service.execute(new Runnable() {
@Override
public void run() {
while(true){
if (queue.isEmpty()){
synchronized (lock){
isRunning = false; //usage of boolean
lock.wait();
}
}
else{
process(queue.remove());
}
}
});
}
//will be called from a single thread but multiple times.
public void addToQueue(CustomClass custObj){
queue.add(custObj);
//I don't want blocking here!!
if (!isRunning){
isRunning = true; //usage of BOOLEAN!
synchronized(lock){
lock.notify();
}
}
}
这里有什么问题吗?谢谢。 修改 目的:这种方式当第二次调用add()时,它将不会被notify()阻塞。有没有更好的方法来实现主线程的这种非阻塞行为?
答案 0 :(得分:0)
虽然您没有显示addToQueue
代码,但我相当确定此代码无法正常工作,因为您在没有任何同步的情况下访问共享队列(不是线程安全的)。
process(queue.remove());
而不是尝试让您的自定义队列工作(我怀疑您的计划是否可以使用布尔标志),节省时间和工作并使用其中一个提供的BlockingQueues或ConcurrentLinkedQueue JDK。
答案 1 :(得分:0)
队列未同步,因此上述代码可能会遇到条件变量和监视器典型的丢失唤醒调用。 https://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem 例如,这是一个有问题的序列: 在运行开始时,Q为空,isRunning为false。 线程1(t1)检查Q是否为空(这是真的)然后停止运行。 比线程2(t2)开始运行并执行addToQ方法。 然后t1继续运行并等待锁定,尽管Q不为空。 如果你想要一个非阻塞的解决方案你可以使用非阻塞Q java提供(http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ConcurrentLinkedQueue.html)Of当然,你可以使用java自己的blockingQueue,但这是阻塞。