线程协作(生产者消费者问题)
线程同步问题,生产者和消费者共享同一个资源,并且生产者和消费者之间相互依赖,互为条件。
分析:
生产者------没有生产产品之前,要通知消费者等待,生产产品之后,需要通知消费者消费;
消费者------在消费完之后,要通知生产者消费结束,需要生产新的产品,以供消费。
在这个问题中,只是用synchronized远远不够,因为,synchronized不能用来实现不同线程之间的消息传递。这个时候就需要使用线程通信来实现不同线程之间的通信。
使用线程通信方法
方法名 | 作用 |
---|---|
wait() | 表示线程一直等待,知道其他线程通知,释放线程上的锁 |
wait(long timeout) | 指定等待毫秒数 |
notify() | 唤醒一个处于等待状态的线程 |
notifyAll() | 唤醒同一个对象上所有调用wait()方法的线程,优先级高的先调度 |
这些方法只能在同步方法或者同步代码块中使用。
两种方法解决生产者消费者问题
管程法
/**
* 管程法:解决生产者——消费者问题
*/
public class TestPc {
public static void main(String[] args) {
SynContainer container = new SynContainer();
new Producer(container).start();
new Consumer(container).start();
}
}
//生产者
class Producer extends Thread {
SynContainer container;
public Producer(SynContainer container) {
this.container = container;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
container.push(new Chicken(i));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("生产了" + i + "只鸡");
}
}
}
//消费者
class Consumer extends Thread {
SynContainer container;
public Consumer(SynContainer container) {
this.container = container;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
System.out.println("消费了" + container.pop().id + "只鸡");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Chicken {
int id;
public Chicken(int id) {
this.id = id;
}
}
class SynContainer {
//容器大小
Chicken[] chickens = new Chicken[10];
int count = 0;
public synchronized void push(Chicken chicken) throws InterruptedException {
//如果容器满了,需要等待消费者消费
if (count == chickens.length) {
this.wait();
}
//如果没有满,丢入产品
chickens[count] = chicken;
count++;
this.notifyAll();
}
public synchronized Chicken pop() throws InterruptedException {
//判断是否可以消费
if (count == 0) {
//消费者等待生产者生产
this.wait();
}
count --;
Chicken chicken = chickens[count];
//消费者消费完了,通知生产者生产
this.notifyAll();
return chicken;
}
}
信号灯法
package syn;
/**
* 信号灯法解决生产者——消费者问题
* 厨师生产,食客消费
*/
public class TestPC3 {
public static void main(String[] args) {
Food food = new Food();
new Cooker(food).start();
new Diners(food).start();
}
}
//生产者--厨师
class Cooker extends Thread {
Food food;
public Cooker(Food food) {
this.food = food;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
try {
this.food.makeFood("鱼香肉丝");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//消费者
class Diners extends Thread{
Food food;
public Diners(Food food){
this.food = food;
}
@Override
public void run() {
for (int i = 0;i < 20;i++) {
try {
this.food.eat();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//产品 -- 食物
class Food{
String foodName;
boolean flag = true;
//厨师做饭
public synchronized void makeFood(String foodName) throws InterruptedException {
if (!flag) {
this.wait();
}
System.out.println("厨师做了" + foodName);
//通知食客可以吃了
this.notifyAll();
this.foodName = foodName;
this.flag = !this.flag;
}
//食客吃饭
public synchronized void eat() throws InterruptedException {
if (flag) {
this.wait();
}
System.out.println("吃了" + foodName);
this.notifyAll();
this.flag = !this.flag;
}
}