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

-迷糊- 2013-03-05 05:05:26
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吗?
...全文
1900 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
godwanglong 2013-03-11
  • 打赏
  • 举报
回复
“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中也的确存在这个现象
chaofengwang09 2013-03-08
  • 打赏
  • 举报
回复
最近在搞udp 这些方法都没怎么用了 学习了
iwome 2013-03-07
  • 打赏
  • 举报
回复
你去搜索下 WaitForSingleObject WaitForMultipleObject 的java实现版本,那个东西比较通用,控制多线程之间的协调很方便。
-迷糊- 2013-03-06
  • 打赏
  • 举报
回复
引用 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
小菜的粉丝 2013-03-06
  • 打赏
  • 举报
回复
又学到新知识了,不错!
浪漫小和 2013-03-06
  • 打赏
  • 举报
回复
赞一个,研究官方的doc得出结论,这才是学习之道
yongger520 2013-03-06
  • 打赏
  • 举报
回复
引用 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得出结论,这才是学习之道 而我开始只是猜测
dracularking 2013-03-06
  • 打赏
  • 举报
回复
我找到的这个(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了
龙四 2013-03-06
  • 打赏
  • 举报
回复
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.
龙四 2013-03-06
  • 打赏
  • 举报
回复
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.
dracularking 2013-03-05
  • 打赏
  • 举报
回复
引用 4 楼 dy110936 的回复:
引用 3 楼 dracularking 的回复:推荐的wait使用方式是这样的: synchronized (obj) { while (<condition does not hold>) obj.wait(); ... // Perform action appropriate to condi……
不wait是因为使用的同步锁对象的关系,b对象是一个Thread对象,该thread执行完毕后,会调用notifyAll方法,唤醒等待在该线程对象上的所有线程。
yanxing2012 2013-03-05
  • 打赏
  • 举报
回复
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方法执行完,不需要去唤醒同步的对象,仅是猜测。。。
-迷糊- 2013-03-05
  • 打赏
  • 举报
回复
引用 2 楼 yanxing2012 的回复:
唤醒三种方式:1.时间到期。即线程在指定一段时间过去后会醒过来。2.线程被中断。其他线程调用此线程的interrupt()方法。3.对象得到通知。
这三条应该都没有满足吧1.没有设置wait的超时时间。2.没调用interrupt。3.没调用notify
-迷糊- 2013-03-05
  • 打赏
  • 举报
回复
引用 3 楼 dracularking 的回复:
推荐的wait使用方式是这样的: synchronized (obj) { while (<condition does not hold>) obj.wait(); ... // Perform action appropriate to condition } 如果不加whil……
哦,这样啊。 那就是说就不用notify的话,wait也会唤醒吗? 那么唤醒的时机又在什么时候呢? orz
dracularking 2013-03-05
  • 打赏
  • 举报
回复
推荐的wait使用方式是这样的: synchronized (obj) { while (<condition does not hold>) obj.wait(); ... // Perform action appropriate to condition } 如果不加while,貌似就会得到楼主所观察到的现象
yanxing2012 2013-03-05
  • 打赏
  • 举报
回复
唤醒三种方式:1.时间到期。即线程在指定一段时间过去后会醒过来。2.线程被中断。其他线程调用此线程的interrupt()方法。3.对象得到通知。
yongger520 2013-03-05
  • 打赏
  • 举报
回复
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又是线程又作为同步用途,看起来别扭

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧