首页 > 代码库 > java 22 - 17 多线程之等待唤醒机制(接16)
java 22 - 17 多线程之等待唤醒机制(接16)
先来一张图,看看什么叫做等待唤醒机制
接上一章的例子。
例子:学生信息的录入和获取
* 资源类:Student
* 设置学生数据:SetThread(生产者)
* 获取学生数据:GetThread(消费者)
* 测试类:StudentDemo
* 资源类:Student (为了使用等待唤醒机制,添加了个布尔类型的变量,默认为flase)
1 public class Student {2 String name;3 int age;4 boolean flag; // 默认情况是没有数据,如果是true,说明有数据5 }
* 设置学生数据:SetThread(生产者)
1 public class SetThread implements Runnable { 2 3 private Student s; 4 private int x = 0; 5 6 public SetThread(Student s) { 7 this.s = s; 8 } 9 10 @Override11 public void run() {12 while (true) {13 synchronized (s) {14 //判断有没有15 if(s.flag){16 try {17 s.wait(); //t1等着,释放锁18 } catch (InterruptedException e) {19 e.printStackTrace();20 }21 }22 23 if (x % 2 == 0) {24 s.name = "张三";25 s.age = 23;26 } else {27 s.name = "李四";28 s.age = 24;29 }30 x++; //x=131 32 //修改标记33 s.flag = true;34 //唤醒线程35 s.notify(); //唤醒t2,唤醒并不表示你立马可以执行,必须还得抢CPU的执行权。36 }37 //t1有,或者t2有38 }39 }40 }
* 获取学生数据:GetThread(消费者)
1 public class GetThread implements Runnable { 2 private Student s; 3 4 public GetThread(Student s) { 5 this.s = s; 6 } 7 8 @Override 9 public void run() {10 while (true) {11 synchronized (s) {12 if(!s.flag){13 try {14 s.wait(); //t2就等待了。立即释放锁。将来醒过来的时候,是从这里醒过来的时候15 } catch (InterruptedException e) {16 e.printStackTrace();17 }18 }19 20 System.out.println(s.name + "---" + s.age);21 //张三---2322 //李四---2423 24 //修改标记25 s.flag = false;26 //唤醒线程27 s.notify(); //唤醒t128 }29 }30 }31 }
* 测试类:StudentDemo
1 public class StudentDemo { 2 public static void main(String[] args) { 3 //创建资源 4 Student s = new Student(); 5 6 //设置和获取的类 7 SetThread st = new SetThread(s); 8 GetThread gt = new GetThread(s); 9 10 //线程类11 Thread t1 = new Thread(st);12 Thread t2 = new Thread(gt);13 14 //启动线程15 t1.start();16 t2.start();17 }18 }
来,依次分析这段代码:
①假设消费者GetThread先抢到了CPU的资源:
则先执行这段代码:
1 public void run() { 2 while (true) { //true,进来 3 synchronized (s) { 4 if(!s.flag){ //因为是消费者先进来,所以里面没有“包子”,而s.flag的默认值是flase,这里取反,就true,进来 5 try { 6 s.wait(); //没“包子”,等待,并且释放锁。下次唤醒它的时候,是从这里唤醒,并不是从头开始执行 7 } catch (InterruptedException e) { 8 e.printStackTrace(); 9 }10 }11 12 System.out.println(s.name + "---" + s.age);13 14 15 s.flag = false;16 17 s.notify(); 18 }19 }20 }
②由于消费者在等待,并且释放了锁。则消费者和生产者继续抢CPU的资源,而消费者抢到的话,依旧等待,直到生产者(SetThread)抢到CPU的资源:
public void run() { while (true) { synchronized (s) { if(s.flag){//判断有没有“包子”,这时候是没有的,s.flag = false,执行下面的if语句 try { s.wait(); //t1等着,释放锁 } catch (InterruptedException e) { e.printStackTrace(); } } //首先x = 0,先录入张三 if (x % 2 == 0) { s.name = "张三"; s.age = 23; } else { s.name = "李四"; s.age = 24; } x++; //x=1//这时候已经有“包子”了,就修改标志 s.flag = true; //唤醒线程 s.notify(); //唤醒t2,唤醒并不表示你立马可以执行,必须还得抢CPU的执行权。 } //t1继续抢到执行权,或者t2抢到执行权 } }
③若是t1继续抢到执行权:
1 synchronized (s) {2 3 if(s.flag){//这个时候已经有了张三这个“包子”,而且flag = true;,所以进来4 try {5 s.wait(); //t1等待,并且释放锁,t1和t2抢占CPU资源,t1抢到继续等待,t2抢到就执行t26 } catch (InterruptedException e) {7 e.printStackTrace();8 }9 }
④t2抢到执行权:
1 public void run() { 2 while (true) { //true,进来 3 synchronized (s) { 4 if(!s.flag){ //有“包子”,这时候的flag = true ,!s.flag = flase;不进来 5 try { 6 s.wait(); 7 } catch (InterruptedException e) { 8 e.printStackTrace(); 9 }10 }11 //消费“包子”12 System.out.println(s.name + "---" + s.age);13 14 //修改标记15 s.flag = false;16 //唤醒线程t117 s.notify(); 18 }
//唤醒t1,唤醒并不表示你立马可以执行,必须还得抢CPU的执行权。
19 }
20 }
java 22 - 17 多线程之等待唤醒机制(接16)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。