【线程间通信:等待唤醒机制】
在线程安全解决之后,还是一样存在着如下的问题:
A:如果消费者先抢到CPU的执行权,就会去消费数据,但是现在的数据是默认值,没有意义,应该等着数据有意义,再消费。
B:如果生产者先抢到CPU的执行权,就会去生产数据,但是呢,它生产完数据后,还继续拥有执行权,它又继续产生数据。这是有问题的,它应该等着消费者把数据消费掉,然后再生产。
正常的思路:
A:生产者:先看是否有数据,有就等待,没有就生产,生产完后通知消费者来消费数据。
B:消费者:先是是否有数据,有就消费,没有就等待,通知生产者生产数据。
为了处理这样的问题,JAVA就提供了一种机制,等待唤醒机制。
等待唤醒: Object 类中提供了三个方法:
wait():等待
notify():唤醒单个线程
notifyAll():唤醒所有线程
为什么这些方法不定义在Thread类中呢?
这些方法的调用必须通过锁对象调用,要所有锁对象都可以调用的话,方法就应该在他们共有的父类上,也就是Object类。
例子:线程间通信:生产者消费者(等待唤醒机制)
package com.test; public class Student { String name; int age; boolean isTrue; public synchronized void set(String name, int age) { /**如果有数据,就等待*/ if (this.isTrue) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } /**设置数据*/ this.name = name; this.age = age; /**修改标记*/ this.isTrue = true; this.notify(); } public synchronized void get() { /**如果没有数据,就等待*/ if (!this.isTrue) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } /**获取数据*/ System.out.println(this.name + "---" + this.age); /**修改标记*/ this.isTrue = false; this.notify(); } }
package com.test; public class SetThread implements Runnable { private Student s; private int x = 0; public SetThread(Student s) { this.s = s; } @Override public void run() { while (true) { if (x % 2 == 0) { s.set("叶胖子", 27); } else { s.set("王瘦子", 31); } x++; } } }
package com.test; public class GetThread implements Runnable { private Student s; public GetThread(Student s){ this.s = s; } @Override public void run() { while (true){ s.get(); } } }
package com.test; public class StudentTest { public static void main(String[] args) { Student s = new Student(); SetThread st = new SetThread(s); GetThread gt = new GetThread(s); Thread t1 = new Thread(st); Thread t2 = new Thread(gt); t1.start(); t2.start(); } }
终身学习者