一、线程协调与通信
1. 生产者消费者模式
生产者和消费者共享一个资源,并且生产者和消费者之间互为依赖、互为条件
2. 线程通信方法
3. 线程通信解决方式
- 管程法
利用一个缓冲区,生产者 + 消费者 + 缓冲区
/**
* @Author: WanqingLiu
* @Date: 2023/02/04/10:59
* 管程法解决生产者消费者问题
*/
public class TestPC {
public static void main(String[] args) {
SynContainer synContainer = new SynContainer();
Productor productor = new Productor(synContainer);
Consumer consumer = new Consumer(synContainer);
productor.start();
consumer.start();
}
}
// 生产者
class Productor extends Thread{
SynContainer synContainer;
public Productor(SynContainer synContainer){
this.synContainer = synContainer;
}
@Override
public void run() {
for (int i=0; i<100; i++){
System.out.println("生产了" + i + "号位置的只因");
synContainer.push(new Chicken(i));
}
}
}
// 消费者
class Consumer extends Thread{
SynContainer synContainer;
public Consumer(SynContainer synContainer){
this.synContainer = synContainer;
}
@Override
public void run() {
for (int i=0; i<100; i++){
System.out.println("消费了" + i + "号 id 的只因");
synContainer.pop();
}
}
}
// 产品
class Chicken{
int id;
public Chicken(int id) {
this.id = id;
}
}
// 缓冲区
class SynContainer {
// 容器大小
Chicken[] chickens = new Chicken[10];
// 容器计数器
int cnt = 0;
// 生产者生产
public synchronized void push(Chicken chicken){
if(cnt == chickens.length){
// 通知消费者消费,等待生产\
try {
this.wait();
} catch (InterruptedException e){
e.printStackTrace();
}
}
// 未满,生产
chickens[cnt] = chicken;
cnt++;
// 生产完,通知消费者消费
this.notifyAll();
}
// 消费者消费
public synchronized Chicken pop(){
// 判断能否消费
if(cnt == 0){
// 等待生产者生产
try {
this.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
// 消费
cnt--;
Chicken chicken = chickens[cnt];
// 消费完,通知生产者生产
this.notifyAll();
return chicken;
}
}
- 信号灯法
信号灯法通过设置标志位解决
/**
* @Author: WanqingLiu
* @Date: 2023/02/04/11:17
* 生产者消费者问题 —— 信号灯法
*/
public class TestPC2 {
public static void main(String[] args) {
TV tv = new TV();
new Player(tv).start();
new Watcher(tv).start();
}
}
// 生产者 —— 演员
class Player extends Thread {
TV tv = new TV();
public Player(TV tv){
this.tv = tv;
}
@Override
public void run() {
for (int i=0; i<20; i++){
if(i % 2 == 0){
this.tv.play("韩国医学生小姐姐 vlog");
} else {
this.tv.play("广告 -- ");
}
}
}
}
// 消费者 —— 观众
class Watcher extends Thread {
TV tv = new TV();
public Watcher(TV tv){
this.tv = tv;
}
@Override
public void run() {
for (int i=0; i<20; i++){
this.tv.watch();
}
}
}
// 产品 —— 节目
class TV {
// 表演的节目
String show;
boolean flag = true;
// 表演
public synchronized void play(String show){
// 等待观众观看
if (!flag) {
try {
this.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println("演员表演了" + show);
// 通知观众观看
this.notifyAll();
this.show = show;
this.flag = !this.flag;
}
// 观看
public synchronized void watch(){
// 等待演员表演
if (flag) {
try {
this.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
// 观看
System.out.println("观众观看了" + this.show);
// 通知演员表演
this.notifyAll();
this.flag = !this.flag;
}
}