我们都知道线程睡眠的方法有两种,一中是Thread.sleep(),一中是Object实例化对象.wait()。
今天我们着重说一下wait()的作用,我们都知道wait()如果没有参数的话线程会一直处于睡眠状态,除非主动唤醒,主动唤醒的方式有两种:notify()或者notifyAll();
现在我们来使用wait()以及notifyAll()来实现线程通信。
首先我们假定一个场景:有四个角色,分别是厨房,食客,鸡,以及存放鸡的器皿。
厨房:负责将鸡烹饪好。
食客:负责吃鸡。
器皿:盛放烹饪好的鸡。
鸡:被烹饪、被吃。
看一下代码:
/**
* 食物
* 鸡
*/
class Chicken {
//鸡的名字 编号
private String name;
public Chicken(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
/**
* 食客
* 负责吃鸡
*/
class Customor extends Thread{
Container container;
public Customor(Container container) {
this.container = container;
}
@Override
public void run() {
try {
for (int i = 0; i < 50; i++) {
System.out.println("食客消费了一只鸡:"+container.eat().getName());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 厨房
* 负责做食物 鸡
*
*/
class Kitchen extends Thread{
Container container;
public Kitchen(Container container) {
this.container = container;
}
@Override
public void run() {
for (int i = 0; i < 50; i++) {
try {
System.out.println("厨房生产了一只鸡:"+i);
container.pop(new Chicken(i+""));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Container {
/**
* 鸡容器 最多放十只鸡
*/
private Chicken [] chickens = new Chicken[10];
/**
* 鸡的数量
*/
int size = 0;
/**
* 食客吃掉一只鸡
*/
public synchronized Chicken eat() throws InterruptedException {
// 等待生产者生产,消费者等待
//如果鸡没有吃完则消费者可以吃掉一只鸡
if(size == 0){
this.wait();
}
size--;
Chicken chicken = chickens[size];
//唤醒所有等待线程
this.notifyAll();
return chicken;
}
/**
* 厨房做出一只鸡
*/
public synchronized void pop(Chicken chicken) throws InterruptedException {
// 如果记得数量等于器皿的存放数量
// 通知消费者消费 生产者等待
if(size == chickens.length){
this.wait();
}
//不等于器皿数量则添加一只鸡到指定位置
chickens[size] = chicken;
size++;
//唤醒所有等待线程
this.notifyAll();
}
}
调用类:
public class ThreadCommication {
public static void main(String[] args) {
//容器
Container container = new Container();
//厨房 并将容器 丢给厨房
Kitchen kitchen = new Kitchen(container);
//食客 和厨房共享一个容器
Customor customor = new Customor(container);
//启动线程
kitchen.start();
customor.start();
}
}
如果厨房生产出来的鸡
已经到达器皿的容纳大小
,则厨房
停止生产,并通知食客去吃鸡
,否则继续生产鸡
。
如果鸡的数量不为零
,食客则可以一直取鸡吃。否则等待,并通知厨房生产。
厨房生产了一只鸡:0
食客消费了一只鸡:0
厨房生产了一只鸡:1
食客消费了一只鸡:1
厨房生产了一只鸡:2
食客消费了一只鸡:2
厨房生产了一只鸡:3
厨房生产了一只鸡:4
食客消费了一只鸡:3
食客消费了一只鸡:4
厨房生产了一只鸡:5
厨房生产了一只鸡:6
食客消费了一只鸡:5
厨房生产了一只鸡:7
食客消费了一只鸡:6
厨房生产了一只鸡:8
食客消费了一只鸡:7
厨房生产了一只鸡:9
厨房生产了一只鸡:10
食客消费了一只鸡:8
食客消费了一只鸡:10
食客消费了一只鸡:9
厨房生产了一只鸡:11
厨房生产了一只鸡:12
食客消费了一只鸡:11
食客消费了一只鸡:12
厨房生产了一只鸡:13
厨房生产了一只鸡:14
食客消费了一只鸡:13
食客消费了一只鸡:14
厨房生产了一只鸡:15
厨房生产了一只鸡:16
食客消费了一只鸡:15
食客消费了一只鸡:16
厨房生产了一只鸡:17
厨房生产了一只鸡:18
食客消费了一只鸡:17
食客消费了一只鸡:18
厨房生产了一只鸡:19
厨房生产了一只鸡:20
食客消费了一只鸡:19
食客消费了一只鸡:20
厨房生产了一只鸡:21
厨房生产了一只鸡:22
食客消费了一只鸡:21
食客消费了一只鸡:22
厨房生产了一只鸡:23
厨房生产了一只鸡:24
食客消费了一只鸡:23
厨房生产了一只鸡:25
食客消费了一只鸡:24
食客消费了一只鸡:25
厨房生产了一只鸡:26
厨房生产了一只鸡:27
食客消费了一只鸡:26
厨房生产了一只鸡:28
食客消费了一只鸡:27
食客消费了一只鸡:28
厨房生产了一只鸡:29
厨房生产了一只鸡:30
食客消费了一只鸡:29
食客消费了一只鸡:30
厨房生产了一只鸡:31
厨房生产了一只鸡:32
食客消费了一只鸡:31
厨房生产了一只鸡:33
食客消费了一只鸡:32
食客消费了一只鸡:33
厨房生产了一只鸡:34
厨房生产了一只鸡:35
食客消费了一只鸡:34
食客消费了一只鸡:35
厨房生产了一只鸡:36
厨房生产了一只鸡:37
食客消费了一只鸡:36
厨房生产了一只鸡:38
食客消费了一只鸡:37
厨房生产了一只鸡:39
食客消费了一只鸡:38
食客消费了一只鸡:39
厨房生产了一只鸡:40
厨房生产了一只鸡:41
食客消费了一只鸡:40
食客消费了一只鸡:41
厨房生产了一只鸡:42
厨房生产了一只鸡:43
食客消费了一只鸡:42
食客消费了一只鸡:43
厨房生产了一只鸡:44
厨房生产了一只鸡:45
食客消费了一只鸡:44
食客消费了一只鸡:45
厨房生产了一只鸡:46
厨房生产了一只鸡:47
食客消费了一只鸡:46
食客消费了一只鸡:47
厨房生产了一只鸡:48
厨房生产了一只鸡:49
食客消费了一只鸡:48
食客消费了一只鸡:49
总结:我们通过wait()以及notifyAll()方法,实现了,厨房与食客间的互动,使线程永远处于通信状态。