线程通信:等待、唤醒
Object方法 | 这些方法在拥有资源时才能调用 |
---|---|
notify | 唤醒某个线程。唤醒后不是立马执行,而是等CPU分配 |
wait | 等待,释放锁,不占用CPU资源 |
notifyAll | 唤醒全部等待的线程 |
重点:资源的有效利用
生产一个,消费一个;再生产一个,再消费一个
以热干面为例(生产者消费者问题):
class 热干面 {int isOK = 0;
}
class 生产者 implements Runnable {热干面 m;public 生产者(热干面 m) {this.m = m;}public void 做面() {try {synchronized (m) {if (m.isOK > Desk.BUFFER_MAX) {System.out.println("+等需要做了再做");m.wait();System.out.println("+开始做");}m.isOK++;System.out.println("+做面" + m.isOK);m.notify();}} catch (Exception e) {e.printStackTrace();}}public void run() {while (true) {try {Thread.sleep(Desk.做面时间);} catch (InterruptedException e) {e.printStackTrace();}做面(); // 生产面}}
}
class 消费者 implements Runnable {热干面 m;public 消费者(热干面 m) {this.m = m;}public void 吃面() {try {synchronized (m) {// # 锁住面对象if (m.isOK <= 0) {System.out.println("------等面");m.wait();// 等待,释放锁System.out.println("------有面了");}System.out.println("------吃面:" + m.isOK);m.isOK--;m.notify();// 唤醒另一个线程,但是,俩线程等CPU执行权}} catch (Exception e) {e.printStackTrace();}}public void run() {while (true) {try {Thread.sleep(Desk.吃面时间);} catch (InterruptedException e) {e.printStackTrace();}吃面();}}
}
class Desk {// 为了管理对象、模拟现实场景,可以不要public static final int 做面时间 = 100;public static final int 吃面时间 = 100;public static final int BUFFER_MAX = 1;热干面 msg = new 热干面();生产者 m = new 生产者(msg);消费者 c = new 消费者(msg);Thread t1 = new Thread(m); // 生产者线程Thread t2 = new Thread(c); // 消费者线程public void fn() {t1.start();t2.start();}
}
public class 生产者消费者问题 {public static void main(String[] args) {Desk d = new Desk();d.fn();}
}