关于多线程中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,貌似就会得到楼主所观察到的现象 --------------------编程问答--------------------
哦,这样啊。
那就是说就不用notify的话,wait也会唤醒吗?
那么唤醒的时机又在什么时候呢? orz
--------------------编程问答--------------------
这三条应该都没有满足吧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方法执行完,不需要去唤醒同步的对象,仅是猜测。。。 --------------------编程问答--------------------
不wait是因为使用的同步锁对象的关系,b对象是一个Thread对象,该thread执行完毕后,会调用notifyAll方法,唤醒等待在该线程对象上的所有线程。 --------------------编程问答--------------------
试了2楼的方法,果然是不加notify就一直等待了!
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了 --------------------编程问答--------------------
赞一个,研究官方的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