java多线程wait()的问题

inuyasha1 2018-12-15 08:21:11
Object类的wait()方法,必须要在同步代码块或者同步方法中使用,所以遇到了下面的问题:

代码1:

public static void main(String[] args) {
String lock = new String();
System.out.println("开始执行main方法");
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(i);
}
}
});
thread.start();
try {
synchronized (lock) {
lock.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main方法执行结束");
}


运行代码1,使用String对象作为监视器对象,代码会在lock.wait();处释放锁,然后中断执行,这没有问题。
-------------------------------------
但是如果我把监视器对象换成了thread对象之后,main方法首先会在wait()代码出停止执行,但是在thread线程的run()方法执行完之后又会继续执行,代码2如下:

public static void main(String[] args) {
String lock = new String();
System.out.println("开始执行main方法");
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(i);
}
}
});
thread.start();
try {
synchronized (thread) {
thread.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main方法执行结束");
}

为什么把监视器对象换成了thread对象之后,在thread线程执行完run方法之后还会在已经中断了的thread.wait()处接着运行呢?
非常非常迷惑,万脸懵逼中
...全文
227 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq_39936465 2018-12-17
  • 打赏
  • 举报
回复
main 程序是按顺序进行了, 你执行thread.start();时其实就是执行

public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(i);
}
}

等执行完后才执行
语句块
try {
synchronized (thread) {
thread.wait();
}

下面是 wait()和解锁 notify()一个范例进程块

public synchronized void get() {
while (flag)
try {
wait();
} catch (Exception e) { }
flag = true;
notify();
}
public synchronized void set() {
while (!flag)
try {
wait();
} catch (Exception e) { }
flag = false;
notify();
}




inuyasha1 2018-12-17
  • 打赏
  • 举报
回复
引用 6 楼 qq_39936465 的回复:
这个程序本身就有问题。不管wait的话你的进程都执行完毕了。程序2因为进程执行完毕,所以让进程等待是无效的。程序1因为lock代表了的是String类,就变成了死锁状态,wait()一般安置在进程内,不会放在main里。
对于代码2,main()方法是在主线程里,这里调用 了wait()之后,我并没有显示的调用notify()/notifyAll()来唤醒主线程,所以还是不明白为什么在Thread的run()执行完之后,主线程会被唤醒。 并且代码1不是死锁,是调用wait()释放锁,让出cpu资源,等待通知执行
qq_39936465 2018-12-17
  • 打赏
  • 举报
回复
这个程序本身就有问题。不管wait的话你的进程都执行完毕了。程序2因为进程执行完毕,所以让进程等待是无效的。程序1因为lock代表了的是String类,就变成了死锁状态,wait()一般安置在进程内,不会放在main里。
inuyasha1 2018-12-17
  • 打赏
  • 举报
回复
引用 4 楼 m0_37851980 的回复:
我也有一个线程的问题,是关于死锁的,就发布了那一个问题0.0 可以的话顺便帮我看看。。谢谢嘞
朋友前两天有事情,没有看到。希望你贴一下你的测试代码。你有问题的代码也贴一下,一起分析分析
秋···· 2018-12-17
  • 打赏
  • 举报
回复
看起来最好不要用Thread类的对象作为监视者。。。
秋···· 2018-12-17
  • 打赏
  • 举报
回复

/*
	猜测:
		r是Thread的一个对象
		r.start()会将以r为监视器的线程池中的线程全部开启

	实验以及结果:
		实现另外两个线程,让它们在r.start()之前冻结,
		全程没有使用notify方法,但是主函数线程、第二个线程、
		第三个线程全都被唤醒。

		但是如果让主函数线程睡眠10毫秒再等待,即主线程在r.start()后
		再陷入等待状态,此时主函数不能被唤醒。
		如果主函数线程设置为沉睡0毫秒后等待,主函数依旧可以被唤醒,
		原因是主函数线程在r.start()之前陷入等待。
		
		结果证实了猜测。
*/
class Demo
{
	
	
public static void main(String[] args) {
        String lock = new String();
        System.out.println("开始执行main方法");
        final Thread r = new Thread();

		Thread newThread_1 = new Thread(new Runnable(){
			public void run()
			{
				try
				{
					synchronized(r)
					{
						System.out.println("第二个线程开启");
						System.out.println("第二个线程进入等待");
						r.wait();
					}
				}
				catch (InterruptedException e)
				{
				}
				System.out.println("第二个线程被唤醒");
			}
		});

		Thread newThread_2 = new Thread(new Runnable(){
			public void run()
			{
				try
				{
					synchronized(r)
					{
						System.out.println("第三个个线程开启");
						System.out.println("第三个线程进入等待");
						r.wait();
					}
				}
				catch (InterruptedException e)
				{
				}
				System.out.println("第三个线程被唤醒");
			}
		});	
		
		newThread_1.start();
		newThread_2.start();

		System.out.println("监视器线程开启");
		r.start();
		
		//让主线程沉睡10毫秒。如果沉睡0毫秒则依旧会被唤醒
		try
		{
			Thread.sleep(10);
		}
		catch (InterruptedException e)
		{
		}
		
		//让主函数进入等待状态,观察是否会被唤醒
        try 
		{
            synchronized (r)
			{
				System.out.println("主线程进入等待");
                r.wait();
				System.out.println("主线程被唤醒");
            }
        }
		catch (InterruptedException e)
		{
            e.printStackTrace();
        }
		
        System.out.println("main方法执行结束");
    }

}
秋···· 2018-12-16
  • 打赏
  • 举报
回复
我也有一个线程的问题,是关于死锁的,就发布了那一个问题0.0 可以的话顺便帮我看看。。谢谢嘞
秋···· 2018-12-16
  • 打赏
  • 举报
回复
上面说的不太对,纠正一下:如果监视者是Thread的一个对象,该对象只要一使用start()方法,就会唤醒该监视器的线程池中的当前所有线程
秋···· 2018-12-16
  • 打赏
  • 举报
回复
我也是小白。测试了一晚上,发现以Thread对象为监视器的对象,只要一使用start()方法,就会唤醒该监视器的线程池中的当前所有线程(相当于使用了notifyAll()方法),需要的话我可以贴上我测试的代码
inuyasha1 2018-12-15
  • 打赏
  • 举报
回复
这两处代码的唯一不同的地方是,synchronized的对象监视器不同,由代码的String对象作为监视器换成了代码2的thread作为对象监视器,烦请各位大大解释一下

62,628

社区成员

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

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