各位大神帮我看一道问题:
关于wait和notify的,太纠结了,代码如下:class ThreadDemo{ public static void main(String[] args) {
ThreadA a = new ThreadA();
ThreadB b = new ThreadB();
a.setName("第A个线程");
b.setName("第B个线程");
b.start();
System.out.println(Thread.currentThread().getName() + "is starting...");
synchronized(b)
{
try
{
System.out.println("Waiting a to complete....");
b.wait();
System.out.println("b colpleted ,  now back  to " + Thread.currentThread().getName());
a.start();
}
catch (Exception e)
{
System.out.println("IO");
}
}
}
}class ThreadA extends Thread
{
private int total;
public void run()
{
synchronized(this){
System.out.println(Thread.currentThread().getName()+ " is running ...");
for(int i = 0; i < 10; i++)
{
total += i;
}
System.out.println("total = " + total);
}

}
}class ThreadB extends Thread
{
private int total = 1;
public void run()
{
synchronized(this)
{
System.out.println(Thread.currentThread().getName()+ " is running ...");
for(int i = 1; i < 10; i++)
{
total *= i;
}
System.out.println("total = " + total);
System.out.println("下面执行notify");
notify();
System.out.println("notify  ok");
}

}
}
同一个程序,每次执行的结果不同,分别为以上图片中的两种结果
对于第一个结果来说,notify在wait之前进行的,为什么程序会执行完成了?
附加问题:线程A wait之后,需要由其他的线程notify还是由自己notify?waitnotify

解决方案 »

  1.   

    notify是唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个 wait 方法,在对象的监视器上等待
    所以是你该对象wait了就该对象notify,其次结果不一样很正常 线程 你要理解  main是主线程。。主线程和你new出来的线程start后是一起执行的,就像跑步 只是在不同轨道上 所以有快有慢  谁知道哪个线程简单或者复杂而导致该线程运行快或者慢呢?不过总是要回到主线程的
      

  2.   

    线程A wait之后,需要由其他的线程notify,自己是不能唤醒自己的
      

  3.   

    调用notify之后,并不是立即释放锁。 而是要等到同步块执行完之后  再释放锁。线程A wait之后它就相当于已经睡着了,已经不会做任何操作了 ,只能通过其它线程去调用它的notify方法去唤醒它。
      

  4.   

    楼主这个代码的关键是用了一个线程对象 b 作为同步对象了。用线程对象做同步对象就个特点,它会在这个线程结束后唤醒这个对象的wait()的等待状态。(MiceRice 说是会运行notifyAll()方法)。
         当调用这个对象的wait()方法时,这个对象的线程已经结束,则这个等待就无法唤醒了。楼主运行的代码的后面那个结果就是这样的; 而当wait()方法运行时,这个对象的线程还没有结束,那么当这个线程结束的时候,wait()会被唤醒。(楼主的第一种情况)。楼主的代码有两种情况:
    1    主线程先进入同步代码块运行,这时, 先输出“Waiting a to complete....”,这种情况代码会先执行b.wait(), 当执行到这里时,主线程会释放b这个对象的锁,线程b会得到这个锁,运行其代码,在执行到notify()时,会唤醒主线程,正常执行完。(如果没有这个notify()语句,b线程结束后,也会执行一个notifyAll(),也会唤醒调用了wait()的线程)。
        这种情况,发生几率小,本人试了10多次,发现一次。结果如下:mainis starting...
    Waiting a to complete....
    第B个线程 is running ...
    total = 362880
    下面执行notify
    notify  ok
    b colpleted ,  now back  to main
    第A个线程 is running ...
    total = 452    b线程先于主线程运行,b线程先进入同步代码块,主线程因为得不到对象锁,就在阻塞状态。主线程会在b线程的同步代码块运行结束后,会得到对象锁而运行主线程的同步代码块里的代码。这时就是这个代码比较不好理解的地方了。我认为还会有两种情况:
         a 当主线程运行到 b.wait()时,如果b线程已经结束了,那么代码就永远等待下去了。
           测试时,这种情况最多的。
         b 当主线程运行到 b.wait()时,b线程虽然执行完同步代码块了,但还没有结束,这种情况,
           在b线程最后结束时,会唤醒主线程。程序会正常退出。
           这种情况也不易出现。楼主可以参考一下这个帖子,MiceRice(ldh911)有很好的解释。
    http://bbs.csdn.net/topics/390352356还可以把代码加几条语句试试:        synchronized(b)
            {
                try
                {
                    System.out.println("Waiting a to complete....");
                    //----------------------------------------------------------------------------
                    System.out.println("b is alive ? "+b.isAlive());             //看b线程状态。
                    if(b.isAlive())
                    {                                                            //如果b已经不在了,就去等待了。
                        System.out.println("now running wait() method!");        //如果 b.isAlive()为true,会进入这里并输出。
                        b.wait();
                    }
                    //-----
                    System.out.println("b colpleted ,  now back  to " + Thread.currentThread().getName());
                    a.start();
                }