线程通信的应用场景是消费者/生产者问题。就是我们让生产者去生产商品,然后消费者来消费,那么当产品不足的时候我们让消费者这个线程去通知生产者这个线程。如果没有消费者,那么生产者就处于等待状态。
s首先这是一个线程同步的问题,生产者和消费者共享同一个资源,并且生产者和消费者之间有所关联,所以这个问题仅用同步块是不能解决的,因为同步块只能实现同步,并不能实现多个线程之间的信息传递。那在 Java 中我们提供了一些方法来解决线程之间的通信。方法如下表所示:
方法 | 说明 |
---|---|
wait() | 表示线程一直等待,直到接到通知(会释放锁) |
wait(long timeout) | 指定线程等待的毫秒数 |
notify() | 唤醒一个处于等待状态的线程 |
notifyAll() | 唤醒同一个对象上的所有处于等待状态的线程 |
上面这些方法都只能在同步方法或者同步块中使用,否则会抛出 IllegalMonitorStateException 异常。
消费者/生产者模型代码如下:
public class TestPC {
public static void main(String[] args) {
SynContainer synContainer = new SynContainer();
new Productor(synContainer).start();
new Consumer(synContainer).start();
}
}
//生产者
class Productor extends Thread{
//需要向容器中加入产品
SynContainer container;
public Productor(SynContainer container){
this.container = container;
}
@Override
public void run() {
for (int i = 1; i < 100; i++) {
//生产者添加产品
container.push(new Chicken(i));
System.out.println("生产者生产了"+i+"鸡");
}
}
}
//消费者
class Consumer extends Thread{
SynContainer container;
public Consumer(SynContainer container){
this.container = container;
}
@Override
public void run() {
for (int i = 1; i < 100; i++) {
//消费者拿走产品
Chicken chicken = container.pop();
System.out.println("消费者消费了"+chicken.id+"鸡");
}
}
}
//缓冲区-->容器
class SynContainer{
//容器
Chicken[] chickens = new Chicken[10];
//容器的计数器
int num = 0;
//生产者放入产品
public synchronized void push(Chicken chicken) {
//假如容易已经满了,就不用放,等待消费者消费
if (num>=chickens.length){
//等待消费者消费
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//假如容器没有满 , 通知生产生成
System.out.println("num,,,,,"+num);
chickens[num] = chicken;
System.out.println("数组有多少个元素"+num);
num++;
//通知消费者消费
this.notifyAll();
}
//消费者拿走产品
public synchronized Chicken pop(){
//假如容器空的,等待
if (num<=0){
//等待生产
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
num--;
Chicken chicken = chickens[num];
//通知生产者生产
this.notifyAll();
return chicken;
}
}
//产品->鸡
class Chicken {
int id;
public Chicken(int id) {
this.id = id;
}
}
上面的代码就是使用管程法使生产者和消费者进行通信,如果不懂没有关系,因为我也不是很明白。