Java基础教程——线程通信

线程通信:等待、唤醒

Object方法 这些方法在拥有资源时才能调用
notify 唤醒某个线程。唤醒后不是立马执行,而是等CPU分配
wait 等待,释放锁,不占用CPU资源
notifyAll 唤醒全部等待的线程

重点:资源的有效利用

Java基础教程——线程通信

生产一个,消费一个;再生产一个,再消费一个

以热干面为例(生产者消费者问题):

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();
	}
}