大家好,本贴转自www.java-cn.com上面的,由于问题有点棘手,所以上这里请大家帮忙解答一下!这是我第一次来这里提问,希望大家帮忙,我一定在线(上班)的时候关注此问题,并及时给分。
原贴是:
http://www.java-cn.com/bbs-jsp/show.jsp?id=28967&forum=advanced现在我有两点问题:
1.当有两个以上的线程同步运行的时候,为什么一定要把 if 改成 while 
2.最好是将notify函数改用notifyAll() 代替(我试了一下,好像都可以用的啊)。 
代码如下: 
package chapter3; /** 
* @author cherry 两个线程用作Producer,一个线程用作Consumer 
* This version is 2.0 , proposed by 小狗子 
* Date : 2007.4.4 
*/ 
public class Chapter3 { 
public static void main(String[] args) { 
NewThread a, b, c, d; 
Q q = new Q(); 
a = new NewThread("1st producer ", true, q);// Producer 1 
b = new NewThread("2nd producer ", true, q);// Producer 2 
c = new NewThread("3rd producer ", true, q);// Producer 3 
d = new NewThread("1st consumer ", false, q);// Consumer 
Thread t = Thread.currentThread(); 
t.setName("Main thread"); 
System.out.println(t.getName() + " is starting..."); 
try { 
a.t.join(); 
b.t.join(); 
c.t.join(); 
d.t.join(); 
System.out.println("main thread is exiting.........."); 
} catch (InterruptedException e) { 
System.out.println("error occurs" + e.getMessage()); 
} finally { } 

} /** 
* @author cherry Class Q is used to implement comsumer and producer 
*/ 
class Q { 
private static int counter = 0; synchronized void addCounter(String threadName) { 
// must use while condition here,instead of if condition 
while (counter >= 10) {// 生成过剩就等待 
try { 
System.out.println(threadName + " add is waiting"); 
wait(); } catch (InterruptedException e) { 
System.out.println("wait error!"); 


counter += 1; 
notifyAll();// use notify() seems also right here 
System.out.println("add counter: " + counter); 
} synchronized void minCounter(String threadName) { 
// must use while condition here,instead of if condition 
while (counter == 0) {// 消费过渡就等待 
try { 
System.out.println(threadName + " minus is waiting"); 
wait(); 
} catch (InterruptedException e) { 
System.out.println("wait error!"); 


counter -= 1; 
System.out.println("min counter: " + counter); 
notifyAll(); 

} class NewThread implements Runnable { 
public Thread t; private boolean add; Q q; NewThread(String name, boolean add, Q q) { 
t = new Thread(this, name); 
this.add = add; 
this.q = q; 
System.out.println(t.getName() + " is starting..."); 
t.start(); 
} public void run() { 
try { 
while (true) { 
t.sleep(1000); if (add) {// Producer 
System.out.println(t.getName()); 
q.addCounter(t.getName()); 
} else { 
System.out.println(t.getName());// Consumer 
q.minCounter(t.getName()); 


} catch (Exception e) { 
System.out.println("error occurs"); 
} finally { 
System.out.println("thread " + t.getName() 
+ "exiting........................."); 


解决方案 »

  1.   

    老啦,懒得看代码喽.notify和notifyAll的关系吗,给你举个例子比如说包括你在内几个人轮流站岗,每次只有一个人站岗其他人睡觉,每人站岗一段时间,而且只有自己知道自己什么时间开始到什么时间结束.现在你站岗,到换人的时间了你不知道应该是谁了,你怎么办?随便找一个人把它踹醒然后你赶紧跑去睡觉?要是踹对人了还行,他去站岗;要是错了,那个人一看表不该自己自己站岗然后又睡了,结果没人站岗了.人家建议你的办法就是把所有人都踹醒,然后自己赶紧躺下睡觉(不赶紧躺下睡觉肯定要挨揍喽)因为所有人都醒了,所以该谁站岗他自己就去了.至于为什么用while,每次你被人踹醒或者自己醒了都要看看表吧,不能只看第一次,以后醒了就直接去站岗把.
      

  2.   

    哈哈,binny 说的倒是蛮形象的!
    可能使我的没有透彻的理解多线程的运行机制,所以还是想问下:
    1.那些站岗的人不是已经按照优先级排好队了么?这样的话,只需要告诉系统我要人,然后,系统自然就会把排在最前面的那个叫醒的阿,所以,我认为用notify就OK了
    2.在满足第一条的情况下,自然就应该可以用if,因为人肯定是找对了。
      

  3.   

    不要相信什么有优先级   那只是java中的一个参考!
    如果非用不可 也最好只相信 那三个常量!Min  Normal Max
      

  4.   

    "那些站岗的人不是已经按照优先级排好队了么"完全的错误!!!jvm是靠抓阄选人滴...
      

  5.   

    呵呵,楼上地说的是!
    我只是需要找到一个可以站岗的人就够了阿,不应该是严格的按照轮流的顺序站岗的吧。
    所以这个时候用notify应该是可以的啊!
      

  6.   

    兄弟们,你们在做JAVA的时候,就没有遇到过这种问题吗?
    学习Java的朋友,不管怎么样请帮忙UP一下吧,让我们共同进步啊! 
      

  7.   

    真的是令人太失望了!看来,Java的确是已经不再像以前那么风光了,我劝初学者别学习Java了,学了,也只是有份工作而已,没有发展前途啊,虽然现在很多项目都使用java做的,但是那只是代表着过去。
      

  8.   

    Thus, it is best to treat thread priorities only as hints to the scheduler. You should never structure your programs so that their correct functioning depends on priority levels.
    (因此,最好仅将线程的优先级看作一个参考因素,不要吧程序构建为其功能的正确性依赖于优先级)
    摘自core java 7th (二)16页
    有空自己去看下吧,上面关于楼主问的 while ,notify函数和notifyAll() 将的很清楚,太多了,懒的打了