生产者-消费者问题笔记
生产者-消费者问题
- 线程互斥要求
- 生产者之间是互斥的,也即同时只能有一个生产者进行生产
- 消费者之间是互斥的,也即同时只能有一个消费者进行消费
- 生产者消费者之间是互斥的,也即生产者消费者不能同时进行生产和消费
- 线程同步要求
- 容器满时,生产者进行等待
- 容器空是,消费者进行等待
Object的synchronized() wait() notifyAll()实现
两个线程,一个产品
//生产消费共10轮
public class Demo{
public static void main(String[] args){
Goods goods = new Goods();
new Thread(()->{
for(int i=0; i<10; i++){
try{
goods.produce();
}catch(InterruptedException e){
e.printStackTrace();
}
}
},"PRODUCE").start();
new Thread(()->{
for(int i=0; i<10; i++){
try{
goods.consume();
}catch(InterruptedException e){
e.printStackTrace();
}
}
},"CONSUME").start();
}
}
class Goods{
private int number = 0;
public synchronized void produce() throws InterruptedException{
if(number != 0){ //判断
this.wait();
}
number++;//干活
System.out.println(Thread.currentThread().getName() + "Produce" + number);
this.notifyAll(); //通知
}
public synchronized void consume() throws InterruptedException{
if(number != 0){ //判断
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName() + "Consume" + number);
this.notifyAll(); //通知
}
}
四个线程,一个产品
//生产消费共10轮
public class Demo{
public static void main(String[] args){
Goods goods = new Goods();
new Thread(()->{
for(int i=0; i<10; i++){
try{
goods.produce();
}catch(InterruptedException e){
e.printStackTrace();
}
}
},"PRODUCE1").start();
new Thread(()->{
for(int i=0; i<10; i++){
try{
goods.produce();
}catch(InterruptedException e){
e.printStackTrace();
}
}
},"PRODUCE2").start();
new Thread(()->{
for(int i=0; i<10; i++){
try{
goods.consume();
}catch(InterruptedException e){
e.printStackTrace();
}
}
},"CONSUME1").start();
new Thread(()->{
for(int i=0; i<10; i++){
try{
goods.consume();
}catch(InterruptedException e){
e.printStackTrace();
}
}
},"CONSUME2").start();
}
}
class Goods{
private int number = 0;
public synchronized void produce() throws InterruptedException{
/*
这里要用while判断,防止consume在经过if判断后都释放锁,然后一个produce生成一个产品后,两个consume轮流抢到锁,从1到-1,因为之前经过了一个if判断,没有再经过一次判断,所以要改为while
真实情况是,线程被唤醒并抢到资源之后,其实还是满足 if 条件,也就是还需要继续阻塞,不应该被唤醒。
*/
while(number != 0){ //判断
this.wait();
}
number++;//干活
System.out.println(Thread.currentThread().getName() + "Produce" + number);
this.notifyAll(); //通知
}
public synchronized void consume() throws InterruptedException{
while(number != 0){ //判断
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName() + "Consume" + number);
this.notifyAll(); //通知
}
}
Lock和Condition的await() / signal()方法 即管程monitor
四个线程,一个产品
//生产消费共10轮
//生产消费共10轮
public class Demo{
public static void main(String[] args){
Goods goods = new Goods();
new Thread(()->{
for(int i=0; i<10; i++){
try{
goods.produce();
}catch(InterruptedException e){
e.printStackTrace();
}
}
},"PRODUCE1").start();
new Thread(()->{
for(int i=0; i<10; i++){
try{
goods.produce();
}catch(InterruptedException e){
e.printStackTrace();
}
}
},"PRODUCE2").start();
new Thread(()->{
for(int i=0; i<10; i++){
try{
goods.consume();
}catch(InterruptedException e){
e.printStackTrace();
}
}
},"CONSUME1").start();
new Thread(()->{
for(int i=0; i<10; i++){
try{
goods.consume();
}catch(InterruptedException e){
e.printStackTrace();
}
}
},"CONSUME2").start();
}
}
class Goods{
private int number = 0;
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void produce() throws InterruptedException{
lock.lock();
try{
while(number != 0){
condition.await();
}
number ++;
System.out.println(Thread.currentThread().getName() + "Produce" + number);
condition.signalAll();
}finally{
lock.unlock();
}
}
public void consume() throws InterruptedException{
lock.lock();
try{
while(number != 0){
condition.await();
}
number ++;
System.out.println(Thread.currentThread().getName() + "Consume" + number);
condition.signalAll();
}finally{
lock.unlock();
}
}
}
使用信号量Semaphore实现生产者-消费者模式
Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源,在操作系统中是一个非常重要的问题,可以用来解决哲学家就餐问题。Java中的Semaphore维护了一个许可集,一开始先设定这个许可集的数量,可以使用acquire()方法获得一个许可,当许可不足时会被阻塞,release()添加一个许可。
在下列代码中,还加入了另外一个mutex信号量,维护生产者消费者之间的同步关系,保证生产者和消费者之间的交替进行
public class Demo{
private static int count = 0;
final Semaphore notFull = new Semaphore(10);
final Semaphore notEmpty = new Semaphore(0);
final Semaphore mutex = new Semaphore(1);
public static void main(String[] args){
Demo demo = new Demo();
new Thread(demo.new Producer()).start();
new Thread(demo.new Consumer()).start();
new Thread(demo.new Producer()).start();
new Thread(demo.new Consumer()).start();
new Thread(demo.new Producer()).start();
new Thread(demo.new Consumer()).start();
}
class Producer implements Runnable{
public void run(){
for(int i=0; i<10; i++){
try{
Thread.sleep(3000);
}catch(InterruptedException e){
e.printStackTrace();
}
try{
notFull.acquire();
mutex.acquire();
count++;
System.out.println(Thread.currentThread().getName() + "Produce" + count);
}catch(InterruptedException e){
e.printStackTrace();
}finally{
mutex.release();
notEmpty.release();
}
}
}
}
class Consumer implements Runnable{
public void run(){
for(int i=0; i<10; i++){
try{
Thread.sleep(3000);
}catch(InterruptedException e){
e.printStackTrace();
}
try{
notEmpty.acquire();
mutex.acquire();
count--;
System.out.println(Thread.currentThread().getName() + "Consume" + count);
}catch(InterruptedException e){
e.printStackTrace();
}finally{
mutex.release();
notFull.release();
}
}
}
}
}

浙公网安备 33010602011771号