java多线程wait()的问题

[复制链接]
查看11 | 回复10 | 2021-1-27 06:16:19 | 显示全部楼层 |阅读模式
Object类的wait()方法,必须要在同步代码块或者同步方法中使用,所以遇到了下面的问题:
代码1:
publicstaticvoidmain(String[]args){
Stringlock=newString();
System.out.println("开始执行main方法");
Threadthread=newThread(newRunnable(){
@Override
publicvoidrun(){
for(inti=0;i
运行代码1,使用String对象作为监视器对象,代码会在lock.wait();处释放锁,然后中断执行,这没有问题。
-------------------------------------
但是如果我把监视器对象换成了thread对象之后,main方法首先会在wait()代码出停止执行,但是在thread线程的run()方法执行完之后又会继续执行,代码2如下:
publicstaticvoidmain(String[]args){
Stringlock=newString();
System.out.println("开始执行main方法");
Threadthread=newThread(newRunnable(){
@Override
publicvoidrun(){
for(inti=0;i
为什么把监视器对象换成了thread对象之后,在thread线程执行完run方法之后还会在已经中断了的thread.wait()处接着运行呢?
非常非常迷惑,万脸懵逼中
分 -->
回复

使用道具 举报

千问 | 2021-1-27 06:16:19 | 显示全部楼层
这两处代码的唯一不同的地方是,synchronized的对象监视器不同,由代码的String对象作为监视器换成了代码2的thread作为对象监视器,烦请各位大大解释一下


回复

使用道具 举报

千问 | 2021-1-27 06:16:19 | 显示全部楼层
我也是小白。测试了一晚上,发现以Thread对象为监视器的对象,只要一使用start()方法,就会唤醒该监视器的线程池中的当前所有线程(相当于使用了notifyAll()方法),需要的话我可以贴上我测试的代码
回复

使用道具 举报

千问 | 2021-1-27 06:16:19 | 显示全部楼层
上面说的不太对,纠正一下:如果监视者是Thread的一个对象,该对象只要一使用start()方法,就会唤醒该监视器的线程池中的当前所有线程
回复

使用道具 举报

千问 | 2021-1-27 06:16:19 | 显示全部楼层
我也有一个线程的问题,是关于死锁的,就发布了那一个问题0.0可以的话顺便帮我看看。。谢谢嘞
回复

使用道具 举报

千问 | 2021-1-27 06:16:19 | 显示全部楼层
引用4楼m0_37851980的回复:我也有一个线程的问题,是关于死锁的,就发布了那一个问题0.0可以的话顺便帮我看看。。谢谢嘞
朋友前两天有事情,没有看到。希望你贴一下你的测试代码。你有问题的代码也贴一下,一起分析分析
回复

使用道具 举报

千问 | 2021-1-27 06:16:19 | 显示全部楼层
这个程序本身就有问题。不管wait的话你的进程都执行完毕了。程序2因为进程执行完毕,所以让进程等待是无效的。程序1因为lock代表了的是String类,就变成了死锁状态,wait()一般安置在进程内,不会放在main里。
回复

使用道具 举报

千问 | 2021-1-27 06:16:19 | 显示全部楼层
引用6楼qq_39936465的回复:这个程序本身就有问题。不管wait的话你的进程都执行完毕了。程序2因为进程执行完毕,所以让进程等待是无效的。程序1因为lock代表了的是String类,就变成了死锁状态,wait()一般安置在进程内,不会放在main里。
对于代码2,main()方法是在主线程里,这里调用了wait()之后,我并没有显示的调用notify()/notifyAll()来唤醒主线程,所以还是不明白为什么在Thread的run()执行完之后,主线程会被唤醒。
并且代码1不是死锁,是调用wait()释放锁,让出cpu资源,等待通知执行
回复

使用道具 举报

千问 | 2021-1-27 06:16:19 | 显示全部楼层
main程序是按顺序进行了,你执行thread.start();时其实就是执行
publicvoidrun(){
for(inti=0;i
等执行完后才执行
语句块
try{
synchronized(thread){
thread.wait();
}
下面是wait()和解锁notify()一个范例进程块
publicsynchronizedvoidget(){
while(flag)
try{
wait();
}catch(Exceptione){}
flag=true;
notify();
}
publicsynchronizedvoidset(){
while(!flag)
try{
wait();
}catch(Exceptione){}
flag=false;
notify();
}



回复

使用道具 举报

千问 | 2021-1-27 06:16:19 | 显示全部楼层

/*
猜测:
r是Thread的一个对象
r.start()会将以r为监视器的线程池中的线程全部开启
实验以及结果:
实现另外两个线程,让它们在r.start()之前冻结,
全程没有使用notify方法,但是主函数线程、第二个线程、
第三个线程全都被唤醒。
但是如果让主函数线程睡眠10毫秒再等待,即主线程在r.start()后
再陷入等待状态,此时主函数不能被唤醒。
如果主函数线程设置为沉睡0毫秒后等待,主函数依旧可以被唤醒,
原因是主函数线程在r.start()之前陷入等待。
结果证实了猜测。
*/
classDemo
{

publicstaticvoidmain(String[]args){
Stringlock=newString();
System.out.println("开始执行main方法");
finalThreadr=newThread();
ThreadnewThread_1=newThread(newRunnable(){
publicvoidrun()
{
try
{
synchronized(r)
{
System.out.println("第二个线程开启");
System.out.println("第二个线程进入等待");
r.wait();
}
}
catch(InterruptedExceptione)
{
}
System.out.println("第二个线程被唤醒");
}
});
ThreadnewThread_2=newThread(newRunnable(){
publicvoidrun()
{
try
{
synchronized(r)
{
System.out.println("第三个个线程开启");
System.out.println("第三个线程进入等待");
r.wait();
}
}
catch(InterruptedExceptione)
{
}
System.out.println("第三个线程被唤醒");
}
});
newThread_1.start();
newThread_2.start();
System.out.println("监视器线程开启");
r.start();
//让主线程沉睡10毫秒。如果沉睡0毫秒则依旧会被唤醒
try
{
Thread.sleep(10);
}
catch(InterruptedExceptione)
{
}
//让主函数进入等待状态,观察是否会被唤醒
try
{
synchronized(r)
{
System.out.println("主线程进入等待");
r.wait();
System.out.println("主线程被唤醒");
}
}
catch(InterruptedExceptione)
{
e.printStackTrace();
}
System.out.println("main方法执行结束");
}
}

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行