课程相关疑问
package com.imooc.test3; /** * @author LZ * @date 2019/11/25 18:10:12 * @description */ public class Test { public static void main(String[] args) { Goods g = new Goods(); X1 x1 = new X1(g); X2 x2 = new X2(g); Thread t1 = new Thread(x1); Thread t2 = new Thread(x2); t1.start(); t2.start(); } }
package com.imooc.test3; /** * @author LZ * @date 2019/11/25 18:22:22 * @description */ public class Goods { private int money; boolean flag = false; public Goods(){} public Goods(int money){ setMoney(money); } public int getMoney() { return money; } public void setMoney(int money) { this.money = money; } public void save(){ synchronized (this) { if (!flag) { setMoney(getMoney() + 100); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "增加100后的钱为:" + getMoney()); flag = true; notifyAll(); try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } public void draw(){ synchronized (this) { if (flag) { setMoney(getMoney() - 100); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "减少100后的钱为:" + getMoney()); flag = false; notifyAll(); try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }
package com.imooc.test3; /** * @author LZ * @date 2019/11/25 18:10:32 * @description */ public class X1 implements Runnable{ Goods goods; public X1(){} public X1(Goods goods){ this.goods = goods; } @Override public void run() { int i=3; while (i>0) { goods.save(); i--; } } }
package com.imooc.test3; /** * @author LZ * @date 2019/11/25 18:10:38 * @description */ public class X2 implements Runnable{ Goods goods; public X2(){} public X2(Goods goods){ this.goods = goods; } @Override public void run() { int i=3; while (i>0) { goods.draw(); i--; } } }
疑问1.在没有加入wait();和notifyAll();方法时,我打印输出时都是先输出两三个线程1的信息,然后再输出一两个线程2的信息依次循环知道结束,并没有像课程中老师所输出的那样大部分都是线程1,2交替打印信息。我也觉得我输出的很奇怪,因为我代码中也调用了sleep()方法,当线程1休眠时正常来说线程2会马上夺得cup的资源进行输出打印
疑问2.在视频的18:23的时候,老师先调用了wait();方法然后再notifyAll();这里不懂执行顺序,当执行wait()时线程不是进入等待(阻塞)了么,下面的代码(输出语句等待)还会执行么?既然已经阻塞了,它下面调用了notifyAll();方法会不会把刚刚调用了wait()方法的线程也给唤醒了啊,那不就是唤醒了当前线程和另外一共两个线程了
疑问3.同步锁和wait()sleep()notifyAll()等操作线程的方法,在线程类中调用和在被操作的类里面方法调用有什么区别?
正在回答
同学你好,
1、对于同学的第一个疑问。同学所描述的先输出两三个线程1的信息,然后再输出一两个线程2的信息依次循环直到结束,这里是因为在没有添加wait();和notifyAll();时,线程的执行过程是随机的,因为调用sleep()方法,使当前线程进入休眠,大大提高了线程2的获取cpu的概率,这里同学没有实现与老师类似的效果,一是由于线程的执行过程是随机的,二是建议同学将sleep休眠的方法编写在X1和X2类中,这样才能保证,每执行完一次线程1的方法,进入休眠,线程2才可以获取到cpu。
如:
2、在视频的18:23的时候,老师先调用了wait();方法然后再notifyAll();这里不懂执行顺序,当执行wait()时线程不是进入等待(阻塞)了么,下面的代码(输出语句等待)还会执行么?既然已经阻塞了,它下面调用了notifyAll();方法会不会把刚刚调用了wait()方法的线程也给唤醒了啊,那不就是唤醒了当前线程和另外一共两个线程了
整个的执行顺序是:
首先同学要明白,这里定义flag的目的是为了保证生成数据一个就读取数据一个的效果,初始值为false,
在第一次执行时,当前没有数据生成,所以我们需要调用set()方法去生产数据,也就是执行如下内容,进行输出生产数据的内容,如:
这时,数据生产完毕,有数据了,就需要进行读取数据了,也就是将flag设为true时表示有数据了,可以消费了。所以将flag设置为true。调用notifyAll(),将所有线程唤醒,然后回到Producer类的方法调用处,进行睡眠1s,如:
然后执行下一次的循环,这时执行set()方法,flag为true,则执行wait()方法,将当前线程进入等待。
这时执行消费数据的线程,也就是get()方法,flag为true,不执行语句体,也就是wait()方法,进行获取数据,进行输出,再将flag设为false,表示已经读取完毕。没有数据了。需要再次进行生成数据,最后唤醒线程,将当前线程设为等待。如:
3、同步锁和wait()sleep()notifyAll()等操作线程的方法,在线程类中调用和在被操作的类里面方法调用有什么区别?
synchronized同步锁表示同一时间只能有一个线程进入方法中执行。防止多个线程进入方法进行执行代码,造成数据不一致。
wait()和notifyAll():wait()表示用来使得当前线程进入等待状态,notifyAll()方法:该方法用来唤醒处于等待状态的所有线程。
sleep():表示使当前线程进入休眠。
如果我的回答解决了你的疑惑,请采纳!祝:学习愉快!
同学你好,1、同学所说的输出时都是先输出两三个线程1的信息,然后再输出一两个线程2的信息依次循环,老师测试修改代码并没有复现同学所说的现象。比如
这里同学需要知道一个小知识点:sleep()方法没有释放锁,而wait()方法释放了锁,使得其他线程此时可以使用同步代码块(同步方法)。
2、wait();方法与notifyAll();方法的执行
这里线程并不是直接被唤醒的,因为在前面的执行过程中 第一次flag等于false时,表示没有数据产生,数据为空,此时线程不进入等待,所以执行下面生产数据的代码,进入生产数据,生产完毕,容器中已经有数据, flag设置为true,线程执行进行消费,只有flag判断为ture时,进行消费,这个过程是交换执行,这个是随机的。
两个的线程在执行过程可能会出现,当前线程自己调用了wait()方法进行等待了,会在中途执行另一个线程,这时当前线程为false,而另一个线程可能flag还没执行到为true时,但是同一时间都想要争夺CPU资源来进行生产和消费,就造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。所以要添加notifyAll()进行唤醒线程~
3、wait方法是执行线程等待的方法,synchronized修饰的代码块,就是一段代码被锁起来,不能同步执行这段代码,只能一个一个来执行。notifyAll ()是会通知所有阻塞中的线程重新开始运行。
wait()一般与sychronized关键字搭配使用,因为在JAVA中进程同步是通过synchronized()来实现的,在实现同步机制时,wait()与notify(需要与synchronized()一起使用,实现同步的效果!
如果我的回答解决了你的疑惑,请采纳。祝:学习愉快~
- 参与学习 人
- 提交作业 3802 份
- 解答问题 11489 个
本阶段带你迈入Java世界,学习Java必备基础知识,基础语法、面向对象思想以及常用工具类的使用。
了解课程
恭喜解决一个难题,获得1积分~
来为老师/同学的回答评分吧
0 星