消费者生产者(Java实现)
概述
生产者消费者顾名思义,消费者消费生产者生产的东西。
放到Java代码中如何理解?
我们调一个方法,去改变共享变量,共享变量是多个线程通信的媒介。
也可以这样理解,我们线程是我们代码的执行,如果A线程执行需要B线程的支持或者有一定的依赖关系,那么我们需要两个线程之间通信,A线程改变了共享变量后通知B线程,同理B线程改变了共享变量后通知A线程。
管程法实现
我们用代码实现(管程法:定义一个共享池,共享变量是多个的时候)
package com.yang.kuangTeacher;
import java.util.concurrent.TimeUnit;
/**
* @author: fudy
* @date: 2020/9/13 下午 01:41
* @Decription: 实现生产者消费者问题1(管程法)
**/
public class TestPC1 {
public static void main(String[] args) {
// 只有一个鸡池,保证synchronized锁的同一个对象
ChickenPool chickenPool = new ChickenPool();
new Product(chickenPool).start();
new Consumer(chickenPool).start();
}
}
// 生产者
class Product extends Thread {
ChickenPool chickenPool;
public Product(ChickenPool chickenPool) {
this.chickenPool = chickenPool;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
try {
chickenPool.push(new Chicken(i));
System.out.println("投放了第" + i + "只鸡");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// 消费者
class Consumer extends Thread {
ChickenPool chickenPool;
public Consumer(ChickenPool chickenPool) {
this.chickenPool = chickenPool;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
try {
Chicken pop = chickenPool.pop();
System.out.println("吃了第" + pop.id + "只鸡");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// 鸡腿
class Chicken {
int id;
public Chicken(int id) {
this.id = id;
}
}
// 缓冲区
class ChickenPool {
Chicken[] chickens = new Chicken[10];
int index = 0;
// 生产鸡
public synchronized void push(Chicken chicken) throws InterruptedException {
// 如果池子满了就等待消费
if (index >= chickens.length) {
this.wait();
}
chickens[index] = chicken;
index++;
// 如果生产鸡了就通知消费
this.notifyAll();
}
// 消费鸡
public synchronized Chicken pop() throws InterruptedException {
// 如果没鸡了就等待生产鸡
if (index <= 0) {
this.wait();
}
index--;
Chicken chicken = chickens[index];
TimeUnit.MILLISECONDS.sleep(1000);
// 如果鸡吃完了就通知生产
this.notifyAll();
return chicken;
}
}
信号灯法
如果我们共享变量是个互斥锁,也就是只有一个共享变量,我们可以用一个标识符来当作线程通信的媒介。
package com.yang.kuangTeacher;
import java.util.concurrent.TimeUnit;
/**
* @author: fudy
* @date: 2020/9/13 下午 02:54
* @Decription:
**/
public class TestPC2 {
public static void main(String[] args) {
TV tv= new TV();
new Actor(tv).start();
new Watch(tv).start();
}
}
// 演员
class Actor extends Thread{
TV tv;
public Actor(TV tv){
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
// 为了节目效果,交替执行
if (i % 2 == 0){
try {
this.tv.play("剥夺结衣"+i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
try {
this.tv.play("仓老师"+i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
// 观众
class Watch extends Thread{
TV tv;
public Watch(TV tv){
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
try {
this.tv.watch();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// 电视
class TV{
String tvName ;
boolean flag = true; // 演员是否需要表演
// 表演节目
public synchronized void play(String tvName) throws InterruptedException {
if (!flag){
this.wait();
}else {
System.out.println("演员表演了"+tvName);
this.notifyAll();
this.flag = !this.flag;
this.tvName = tvName;
TimeUnit.SECONDS.sleep(1);
}
}
// 看节目
public synchronized void watch() throws InterruptedException {
if (flag){
this.wait();
}else {
System.out.println("观众看了"+this.tvName);
// TimeUnit.SECONDS.sleep(1);
this.notifyAll();
this.flag = !this.flag;
TimeUnit.SECONDS.sleep(1);
}
}
}
lock锁:
package com.yang.leetcode.other;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author: fudy
* @date: 2020/9/18 上午 09:26
* @Decription:
**/
public class PC {
public static void main(String[] args) {
A a = new A();
new Thread(() -> {
try {
for (int i = 0; i < 20; i++) {
a.increment();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "线程1").start();
new Thread(() -> {
try {
for (int i = 0; i < 20; i++) {
a.decrement();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "线程2").start();
}
}
class A {
private int number = 0;
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
public void increment() throws InterruptedException {
lock.lock();
try {
while (number != 0) {
condition.await();
}
++number;
System.out.println(Thread.currentThread().getName() + "=>" + number);
condition.signalAll();
} finally {
lock.unlock();
}
}
public void decrement() throws InterruptedException {
lock.lock();
try {
while (number == 0) {
condition.await();
}
--number;
System.out.println(Thread.currentThread().getName() + "=>" + number);
condition.signalAll();
} finally {
lock.unlock();
}
}
}
Condition :精准通知
package com.yang.leetcode.other;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author: fudy
* @date: 2020/9/18 上午 09:26
* @Decription:
**/
public class PC {
public static void main(String[] args) {
A a = new A();
new Thread(() -> {
try {
for (int i = 0; i < 20; i++) {
a.increment();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "线程1").start();
new Thread(() -> {
try {
for (int i = 0; i < 20; i++) {
a.decrement();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "线程2").start();
new Thread(() -> {
try {
for (int i = 0; i < 20; i++) {
a.other();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "线程3").start();
}
}
class A {
Lock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
Condition condition3 = lock.newCondition();
private int flag = 1;
public void increment() throws InterruptedException {
lock.lock();
try {
while (flag != 1) {
condition1.await();
}
System.out.println(Thread.currentThread().getName() + "=>" + flag);
flag = 2;
condition2.signal();
} finally {
lock.unlock();
}
}
public void decrement() throws InterruptedException {
lock.lock();
try {
while (flag != 2) {
condition2.await();
}
System.out.println(Thread.currentThread().getName() + "=>" + flag);
flag = 3;
condition3.signal();
} finally {
lock.unlock();
}
}
public void other() throws InterruptedException {
lock.lock();
try {
while (flag != 3) {
condition3.await();
}
System.out.println(Thread.currentThread().getName() + "=>" + flag);
flag = 1;
condition1.signalAll();
} finally {
lock.unlock();
}
}
}