wait应该是只有wait所同步的对象调用notify或者notifyAll才会继续吗?为什么下面代码我没有调用notify,主线程也继续向下执行了?
public class WaitTest {    public static void main(String[] args) {
        ThreadB b = new ThreadB();
        b.start();
        synchronized (b) {
            try {
                System.out.println("Waiting for b to complete...");
                b.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Total is: " + b.total);
        }
    }
}class ThreadB extends Thread {
    int total;
    
    public void run() {
//        synchronized (this) {
            System.out.println("ThreadB");
            for (int i = 0; i < 50; i++) {
                total += i;
                try {
                    Thread.sleep(100);
                    System.out.print(i);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
//            notify();
            System.out.println();
        }
//    }
}PS:还有两个小问题:
1.如果b.wait只能是b.notify才能唤醒吗?那么也必须是b.notifyAll吗?duoxiancheng 多线程

解决方案 »

  1.   

    public class WaitTest {
    public static Object o = new Object(); public static void main(String[] args) {
    ThreadB b = new ThreadB();
    b.start();
    synchronized (o) {
    try {
    System.out.println("Waiting for b to complete...");
    o.wait();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println("Total is: " + b.total);
    }
    }
    } class ThreadB extends Thread {
    int total; public void run() {
    synchronized (WaitTest.o) {
    System.out.println("ThreadB");
    for (int i = 0; i < 50; i++) {
    total += i;
    try {
    Thread.sleep(100);
    System.out.print(i);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    WaitTest.o.notify();
    System.out.println();
    }
    }
    }我的版本,新建一个object用于同步,你的thread又是线程又作为同步用途,看起来别扭
      

  2.   

    唤醒三种方式:1.时间到期。即线程在指定一段时间过去后会醒过来。2.线程被中断。其他线程调用此线程的interrupt()方法。3.对象得到通知。
      

  3.   

    推荐的wait使用方式是这样的:synchronized (obj) {
             while (<condition does not hold>)
                 obj.wait();
             ... // Perform action appropriate to condition
         }如果不加while,貌似就会得到楼主所观察到的现象
      

  4.   


    哦,这样啊。
    那就是说就不用notify的话,wait也会唤醒吗?
    那么唤醒的时机又在什么时候呢? orz
      

  5.   


    这三条应该都没有满足吧1.没有设置wait的超时时间。2.没调用interrupt。3.没调用notify
      

  6.   

    package com.love.yan.xing;class ThreadB extends Thread {
        int total;
         
        public void run() {
    //        synchronized (this) {
                System.out.println("ThreadB");
                for (int i = 0; i < 50; i++) {
                    total += i;
                    try {
                        Thread.sleep(100);
                        System.out.print(i);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                synchronized(new WaitTest().yan()){
                  new WaitTest().yan().notify();
                }
              
                System.out.println();
            }
    //    }
    }package com.love.yan.xing;public class WaitTest {
    static ThreadB b = new ThreadB();
        public static void main(String[] args) {
            
            ThreadB a = new ThreadB();
            a.start();
            synchronized (b) {
                try {
                    System.out.println("Waiting for b to complete...");
                    b.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Total is: " + b.total);
            }
        }
        public Thread yan(){
         return b;
        }
    }
    用以上代码测试了一下,唤醒时,也必须对等待的对象同步。以下猜测:你的代码ThreadB线程,又作为同步对象,首先打印Waiting for b to complete...然后等待,执行的线程和同步的对象是同一个对象,会不会是run方法执行完,不需要去唤醒同步的对象,仅是猜测
      

  7.   


    不wait是因为使用的同步锁对象的关系,b对象是一个Thread对象,该thread执行完毕后,会调用notifyAll方法,唤醒等待在该线程对象上的所有线程。
      

  8.   


    试了2楼的方法,果然是不加notify就一直等待了!wait同步的对象是线程的话,那么同步锁对象(线程)执行完毕后会调用notifyAll?
    第一次听说,学习了...
    有没有相关资料 orz
      

  9.   

    dracularking的说法是正确的。
    see here:http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#join%28long%29As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.
      

  10.   

    http://hg.openjdk.java.net/jdk6/jdk6/hotspot/file/20dbc199874e/src/share/vm/runtime/thread.cpp中1552行void JavaThread::exit(bool destroy_vm, ExitType exit_type)方法中的第1677行有ensure_join(this);调用static void ensure_join(JavaThread* thread)方法在1529行,notifyAll操作在1544行,且方法开头就注释了:// We do not need to grap the Threads_lock, since we are operating on ourself.
      

  11.   

    我找到的这个(method exit from class Thread):/**
         * This method is called by the system to give a Thread
         * a chance to clean up before it actually exits.
         */
        private void exit() {
    if (group != null) {
        group.remove(this);
        group = null;
    }
    /* Aggressively null out all reference fields: see bug 4006245 */
    target = null;
    /* Speed the release of some of these resources */
            threadLocals = null;
            inheritableThreadLocals = null;
            inheritedAccessControlContext = null;
            blocker = null;
            uncaughtExceptionHandler = null;
        }
    /**
         * Removes the specified Thread from this group.
         * @param t the Thread to be removed
         * @return if the Thread has already been destroyed.
         */
        void remove(Thread t) {
    synchronized (this) {
        if (destroyed) {
    return;
        }
        for (int i = 0 ; i < nthreads ; i++) {
    if (threads[i] == t) {
        System.arraycopy(threads, i + 1, threads, i, --nthreads - i);
        // Zap dangling reference to the dead thread so that
        // the garbage collector will collect it.
        threads[nthreads] = null;
        break;
    }
        }
        if (nthreads == 0) {
    notifyAll();
        }
                if (daemon && (nthreads == 0) &&  
                    (nUnstartedThreads == 0) && (ngroups == 0))  
                { 
    destroy();
        }
    }
        }
    但奇怪的是线程退出,其group也被设置为了null,貌似认为当前thread就是当前thread group中的唯一一个thread了
      

  12.   

    赞一个,研究官方的doc得出结论,这才是学习之道
    而我开始只是猜测
      

  13.   

    赞一个,研究官方的doc得出结论,这才是学习之道
      

  14.   


    你去搜索下
    WaitForSingleObject
    WaitForMultipleObject
    的java实现版本,那个东西比较通用,控制多线程之间的协调很方便。
      

  15.   

    “This implementation uses a loop of this.wait calls conditioned on this.isAlive. As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances”这句话在java 7的文档上有的,而在java 6的文档里面没有。不过java 6中也的确存在这个现象