java wait()方法的使用疑问

七月这天 2013-12-19 10:50:54
代码如下所示,如果让线程b等待--b.wait();输出:Total is: 45;但如果把b.wait()这行注释了,可能输出Total is: 0;这个weit()到底起到了什么作用?
public class ThreadA {

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 (Exception e) {
e.printStackTrace();
}
}
System.out.println("Total is: " + b.total);
}
}

class ThreadB extends Thread {
int total;

@Override
public void run() {
for (int i = 0; i < 10; i++) {
total += i;
}
}
}
...全文
611 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
蓝色骨头_cqy 2016-09-07
  • 打赏
  • 举报
回复
引用 4 楼 zxcvbnm11920 的回复:
不知道你这个代码是自己写的还是在那里看的,不知道为了实现什么逻辑。我给你解释下代码是怎么执行的。 b.wait()是让主线程休眠,释放锁。这时b.start还在执行,没执行完,当执行完时会唤醒b对象监听的所有线程,主线程被唤醒了,这时total已经被加到45了,所以会打出45。 如果b.wait()注释掉,2个线程是并行的,b.run里的代码还没执行到就会输出0,执行到就会输出45,你机器上打出0,在我的机器是打出的还是45。打出的数字其实没准。 b.start这个方法执行完时会唤醒b对象监听的所有线程,这个事情挺神奇,我以前还不知道,测试了下才发现这个事。
自己试了一下,b.wait()的确是让主线程阻塞,但是调用wait()被阻塞的线程不是需要notify/notifyAll来唤醒么,这里的当前线程(主线程)没有被唤醒就能继续执行是因为子线程b执行完毕后会自动唤醒主线程??
raphaelg 2015-10-13
  • 打赏
  • 举报
回复
如下这个说法是对的,但楼主这段代码存在main主线程阻塞的风险。如果ThreadB线程执行较快,在main主线程还未执行到sychronized这段代码时就执行完成,那么main主线程就被阻塞住,且永远无法唤醒。
在synchronized (b)这段代码前加上Thread.sleep(1000),就很容易复现出来了。

引用 4 楼 zxcvbnm11920 的回复:
不知道你这个代码是自己写的还是在那里看的,不知道为了实现什么逻辑。我给你解释下代码是怎么执行的。

b.wait()是让主线程休眠,释放锁。这时b.start还在执行,没执行完,当执行完时会唤醒b对象监听的所有线程,主线程被唤醒了,这时total已经被加到45了,所以会打出45。
如果b.wait()注释掉,2个线程是并行的,b.run里的代码还没执行到就会输出0,执行到就会输出45,你机器上打出0,在我的机器是打出的还是45。打出的数字其实没准。

b.start这个方法执行完时会唤醒b对象监听的所有线程,这个事情挺神奇,我以前还不知道,测试了下才发现这个事。
昌汉明 2014-10-16
  • 打赏
  • 举报
回复
引用 7 楼 jrnjsyx 的回复:
有没人能告诉我这里synchronized (b)是做什么用处的呢?
同步两个线程,用于不同线程可以访问同意资源
jrnjsyx 2014-06-03
  • 打赏
  • 举报
回复
有没人能告诉我这里synchronized (b)是做什么用处的呢?
七月这天 2013-12-21
  • 打赏
  • 举报
回复
引用 4 楼 zxcvbnm11920 的回复:
b.start这个方法执行完时会唤醒b对象监听的所有线程,这个事情挺神奇,我以前还不知道,测试了下才发现这个事。
你说的这个问题还真没注意,这是我在网上看到的一段代码,原来的ThreadB是这样的:

class ThreadB extends Thread{
    int total;
    @Override
    public void run(){
        synchronized(this){
            for(int i=0; i<100 ; i++){
                total += i;
            }
            notify();
        }
    }
}
Jw-小超 2013-12-21
  • 打赏
  • 举报
回复
public class ThreadA {

	public static void main(String[] args) {
		ThreadB b = new ThreadB();
		ThreadB b2 = new ThreadB();
		b2.start();
		b.start();
		synchronized (b2) {
			try {
				System.out.println("Waiting for b2 to complete...");
				//b2.wait();
				b.join();
				System.out.println("b Total is: " + b.total);
				b2.wait(1000);
				System.out.println("b2 Total is: " + b2.total);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}

class ThreadB extends Thread {
	int total;

	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			total += i;
		}
	}
}
wait()方法是可以有参数的,延迟多少毫秒。join()方法就是让该进程先运行
骑士的崛起 2013-12-20
  • 打赏
  • 举报
回复
不知道你这个代码是自己写的还是在那里看的,不知道为了实现什么逻辑。我给你解释下代码是怎么执行的。 b.wait()是让主线程休眠,释放锁。这时b.start还在执行,没执行完,当执行完时会唤醒b对象监听的所有线程,主线程被唤醒了,这时total已经被加到45了,所以会打出45。 如果b.wait()注释掉,2个线程是并行的,b.run里的代码还没执行到就会输出0,执行到就会输出45,你机器上打出0,在我的机器是打出的还是45。打出的数字其实没准。 b.start这个方法执行完时会唤醒b对象监听的所有线程,这个事情挺神奇,我以前还不知道,测试了下才发现这个事。
致知Fighting 2013-12-20
  • 打赏
  • 举报
回复
引用 2 楼 qiyuezhetian 的回复:
没人顶,自己顶一下; 一开始以为b.wait()是B线程被等待,看了wait()方法的API后,说是当前线程wait,那就应该是main线程进入等待了,这就能解释为什么main线程就一定会在ThreadB运算之后输出了。 哪位大神来判断下这么理解是否正确。
这个解释是对的,wait之后当前线程会阻塞直到被唤醒,你的代码里,main线程是被阻塞的没错 但是看你的代码,你的理解应该是不对的,b.wait()不是让b线程阻塞,而是当前线程在b这个对象上wait被阻塞
七月这天 2013-12-20
  • 打赏
  • 举报
回复
没人顶,自己顶一下; 一开始以为b.wait()是B线程被等待,看了wait()方法的API后,说是当前线程wait,那就应该是main线程进入等待了,这就能解释为什么main线程就一定会在ThreadB运算之后输出了。 哪位大神来判断下这么理解是否正确。
七月这天 2013-12-19
  • 打赏
  • 举报
回复
如果没有wait()方法我可以理解,main线程在ThreadB运算之前先抢到了资源,输出total为0;我不明白的是为什么加了wait()方法,main线程就一定会在ThreadB运算之后输出。

50,523

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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