当前位置:编程学习 > JAVA >>

关于多线程中wait使用的问题。

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  多线程 --------------------编程问答--------------------
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又是线程又作为同步用途,看起来别扭 --------------------编程问答-------------------- 唤醒三种方式:1.时间到期。即线程在指定一段时间过去后会醒过来。2.线程被中断。其他线程调用此线程的interrupt()方法。3.对象得到通知。 --------------------编程问答-------------------- 推荐的wait使用方式是这样的:

synchronized (obj) {
         while (<condition does not hold>)
             obj.wait();
         ... // Perform action appropriate to condition
     }

如果不加while,貌似就会得到楼主所观察到的现象 --------------------编程问答--------------------
引用 3 楼 dracularking 的回复:
推荐的wait使用方式是这样的:

synchronized (obj) {
         while (<condition does not hold>)
             obj.wait();
         ... // Perform action appropriate to condition
     }

如果不加whil……


哦,这样啊。
那就是说就不用notify的话,wait也会唤醒吗?
那么唤醒的时机又在什么时候呢? orz
--------------------编程问答--------------------
引用 2 楼 yanxing2012 的回复:
唤醒三种方式:1.时间到期。即线程在指定一段时间过去后会醒过来。2.线程被中断。其他线程调用此线程的interrupt()方法。3.对象得到通知。


这三条应该都没有满足吧1.没有设置wait的超时时间。2.没调用interrupt。3.没调用notify --------------------编程问答--------------------
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方法执行完,不需要去唤醒同步的对象,仅是猜测。。。 --------------------编程问答--------------------
引用 4 楼 dy110936 的回复:
引用 3 楼 dracularking 的回复:推荐的wait使用方式是这样的:

synchronized (obj) {
         while (<condition does not hold>)
             obj.wait();
         ... // Perform action appropriate to condi……


不wait是因为使用的同步锁对象的关系,b对象是一个Thread对象,该thread执行完毕后,会调用notifyAll方法,唤醒等待在该线程对象上的所有线程。 --------------------编程问答--------------------
引用 7 楼 dracularking 的回复:
引用 4 楼 dy110936 的回复:引用 3 楼 dracularking 的回复:推荐的wait使用方式是这样的:

synchronized (obj) {
         while (<condition does not hold>)
             obj.wait();
         ... // Perform action ……


试了2楼的方法,果然是不加notify就一直等待了!
引用 1 楼 yongger520 的回复:
Java code public class WaitTest {    public static Object o = new Object();     public static void main(String[] args) {……


wait同步的对象是线程的话,那么同步锁对象(线程)执行完毕后会调用notifyAll?
第一次听说,学习了...
有没有相关资料 orz --------------------编程问答-------------------- dracularking的说法是正确的。
see here:http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#join%28long%29

As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances. --------------------编程问答-------------------- 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. --------------------编程问答-------------------- 我找到的这个(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了 --------------------编程问答--------------------
引用 9 楼 ticmy 的回复:
dracularking的说法是正确的。
see here:http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#join%28long%29

As a thread terminates the this.notifyAll method is invoked. It is recommended that appl……

赞一个,研究官方的doc得出结论,这才是学习之道
而我开始只是猜测
--------------------编程问答-------------------- 赞一个,研究官方的doc得出结论,这才是学习之道
--------------------编程问答-------------------- 又学到新知识了,不错! --------------------编程问答--------------------
你去搜索下
WaitForSingleObject
WaitForMultipleObject
的java实现版本,那个东西比较通用,控制多线程之间的协调很方便。
--------------------编程问答-------------------- 最近在搞udp  这些方法都没怎么用了 学习了 --------------------编程问答-------------------- “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中也的确存在这个现象
补充:Java ,  Java SE
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,