生产者消费者问题
在生产者消费者问题中,仅有synchronized是不够的:
-
synchronized可阻止并发更新同一个共享资源,实现了同步
-
synchronized不能实现不同线程之间的信息传递(通信)
线程通信方法
注意:均是Object类的方法,都只能在同步方法或者同步代码块中使用,否则会抛出异常IIIlegalMonitorStateException
解决方法1
并发协作模式“生产者/消费者模式”——>管程法
生产者将生产好的数据放入缓冲区,消费者从缓冲区拿出数据
public class TestPC {
public static void main(String[] args) {
Container container = new Container();
new Productor(container).start();
new Consumer(container).start();
}
}
//1、需要生产者、消费者、产品和缓冲区
class Productor extends Thread{
Container container;
Productor(Container container){
this.container = container;
}
//生产
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
Chickens chicken = new Chickens(i);
try {
container.put(chicken);
System.out.println("生产者生产了第"+chicken.ID+"只鸡");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer extends Thread{
Container container;
Consumer(Container container){
this.container = container;
}
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
try {
Chickens chicken = container.pop();
System.out.println("消费者消费了第"+chicken.ID+"只鸡");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Chickens{
int ID;//鸡的编号
Chickens(int ID){
this.ID = ID;
}
}
class Container{
//定义一个缓冲区
Chickens[] chickens = new Chickens[10];
int count = 0;//计数器
//2、往缓冲区里面放东西,注意是同步方法
public synchronized void put(Chickens chicken) throws InterruptedException {
//如果缓冲区满了,就通知生产者等待
if(count == chickens.length){
this.wait();
}
//生产者生产并通知消费者消费
chickens[count] = chicken;
count++;
this.notifyAll();
}
//3、取出缓冲区东西
public synchronized Chickens pop() throws InterruptedException {
//如果缓冲区空了,消费者等待
if(count == 0){
this.wait();
}
//消费者消费并通知生产者生产
count--;
Chickens chicken = chickens[count];
this.notifyAll();
return chicken;
}
}
解决方法2
并发协作模式“生产者/消费者模式”——>信号灯法
//信号灯法:标志位
public class TestPC2 {
public static void main(String[] args) {
TV tv = new TV();
new Actor(tv).start();
new Watcher(tv).start();
}
}
//1、演员表演节目,观众观看节目
//演员
class Actor extends Thread{
TV tv;
Actor(TV tv){
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
if(i%2==0){
tv.play("节目一");
}
else {
tv.play("节目二");
}
}
}
}
//观众
class Watcher extends Thread{
TV tv;
Watcher(TV tv){
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
tv.watch();
}
}
}
//节目
class TV{
String programme;//节目名字
//2、标志位 演员表演,观众等待T
// 演员等待,观众看F
boolean flag = true;
//3、表演同步方法
public synchronized void play(String programme){
//如果标志位为假,演员等待
if(!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//演员表演,通知观众观看,改变标志位
this.programme = programme;
System.out.println("演员表演了"+programme);
this.flag = !this.flag;
this.notifyAll();
}
//4、观看同步方法
public synchronized void watch(){
//如果标志位为真,观众等待
if(flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//观众观看,通知演员表演,改变标志位
System.out.println("观众观看了"+this.programme);
this.flag = !this.flag;
this.notifyAll();
}
}
标签:container,生产者,void,通信,tv,flag,TV,线程,public
From: https://www.cnblogs.com/xiluoluo/p/16880511.html