2013-11-28 43 views
0

在第一个Java线程我:Java:只有在等待时才能通知线程?

while (!isDone) { 
    try { 
     synchronized (this) { 
      wait(); 
     } 
    } catch (InterruptedException e) { 
      e.printStackTrace(); 
    } 
    doSomeVeryLongRunningTask(); 
} 

在另一个线程,我想发出一个通知信号:

synchronized (thr1) { 
    thr1.notify(); 
} 

但是,如果doSomeVeryLongRunningTask()方法运行,我不想第二个线程被阻止。我只想通知第一个线程,如果它正在等待,以便第二个线程可以在不锁定的情况下继续执行任务。

我该如何修复上面的代码才能实现这一目标?

回答

2

他们想解决的问题不存在。​​只有当另一个线程已经在同一个对象的​​块同步内时块才会阻塞该线程。由于您的doSomeVeryLongRunningTask()将在​​块之外被调用,因此如果另一个线程位于doSomeVeryLongRunningTask()方法内,通知线程将永远不会被阻止。

但是这引起了另一个问题。你似乎在想,waitnotify调用总是配对。情况并非如此,您可以随时拨打notify,无需任何人倾听。也可能是wait调用返回“虚假”,即没有明显原因。因此,您需要定义另一个“硬条件”,该条件由在​​块内修改并检查的状态定义。

E.g.它的情况下,你在你的thr1变量具有班级里,你可以定义一个boolean标志:

boolean condition; 

然后你修改你等待的方法是这样的:

while(!isDone) { 
    try { 
    synchronized(this) { 
     while(!condition) wait(); 
     if(isDone) break;// skip doSomeVeryLongRunningTask() 
     condition=false; 
    } 
    } catch(InterruptedException e) { 
    e.printStackTrace(); 
    } 
    doSomeVeryLongRunningTask(); 
} 

而且报告代码:

synchronized(thr1) { 
    thr1.condition=true; 
    thr1.notify(); 
} 

这样你的通知代码仍然不会被阻塞(至少永远不会有很长的时间),但等待的线程将等待至少一个通知在一个循环周期内发生。

+0

“您想解决的问题不存在。”感谢您的回复。你帮我看到了我提供的缩短问题的一个问题......'doSomeVeryLongRunningTask()'是一种同步方法。我应该删除那里的同步。您发布的其他解决方案为我提供了一些其他想法。谢谢。 – kmccoy

0

notify()调用不会阻止。只有wait()块。即使没有其他线程在等待,您也可以调用通知,但请确保您的算法是正确的。如果您希望仅通知一次,那么在通知后到达的另一个线程将永远等待()。

+0

notify()不会阻塞 - 但必须在thrd1上进行同步。有没有更好的方法来解决这个问题? – kmccoy

1

看来是什么阻止你的程序不是notify()(它不会阻止),而是在同一个对象上同步的两个​​块。

我不认为你有什么解决方法。检查此链接以知道为什么:http://javarevisited.blogspot.com/2011/05/wait-notify-and-notifyall-in-java.html

+0

我基本上有一个生产者 - 消费者问题,其中消费者有时可能非常缓慢,我不想阻止生产者完成其他任务。这是否有助于潜在地提出一种替代方法来解决生产者在'synchronized(thrd1)'等待中等待的情况? – kmccoy

+1

在这种情况下,您可以使用中间线程安全的数据结构,如Queue。生产者将插入该队列中,消费者将从那里读取。查看一些Queue实现的'java.util.concurrent'包,看看哪个最适合你。 – MondKin

0

建议的模式是使用notifyAll()AND以让所有等待线程在每次通知它们并在开始第一次等待之前检查它们的唤醒条件。

0

在现代Java中同步的速度差不多与--i一样快,因为这是关于硬件compareAndSet机制在内部发生的事情。唯一的情况是,当多于一个线程到达同步块时,因此至少有一个线程必须等待。