Java实现多线程中生产者、消费者问题,简单易懂

思想:

1、生产者在while循环里不停地生产“产品”,每生产一个,就交给店员,店员就得到一个产品

2、消费者在while循环里不停地消费产品,每消费一个,店员就移走一个产品

3、店员手里的产品少于20个,就从生产者那里拿走产品。等于20个,就停止从生产者那里拿走产品

4、店员手里的产品多于0个,就让消费者消费产品。等于0个,就停止让消费者消费产品

 

生产者:

生产者在while循环里不停地生产“产品”,每生产一个,就交给店员,店员就得到一个产品

//生产者
class Producter implements Runnable{
    Clerk clerk;
    Producter(Clerk clerk){
        this.clerk=clerk;
    }
    @Override
    public void run() {
        while (true){
            //此处可加sleep,让生产者生产的慢一点
            clerk.getProduce();//生产者不停地生产产品,生产一个,就交给店员,店员就get一个
        }
    }
}

消费者:

消费者在while循环里不停地消费产品,每消费一个,店员就移走一个产品

//消费者
class Consummer implements Runnable{
    Clerk clerk;
    Consummer(Clerk clerk){
        this.clerk=clerk;
    }
    @Override
    public void run() {
        while (true){
           //此处可加sleep,让消费者消费的慢一些
            clerk.removeProduce();//消费者不停地消费产品,消费一个,店员处就remove一个
        }
    }
}

店员:

店员手里的产品少于20个,就从生产者那里拿走产品。等于20个,就停止从生产者那里拿走产品

店员手里的产品多于0个,就让消费者消费产品。等于0个,就停止让消费者消费产品

//店员
class Clerk{

    public int producenumber;//店员手里产品的数量

    public synchronized void getProduce() {//锁是clerk,反复执行的实际上是该方法和removeProduce方法
        if(producenumber<20){//店员手里产品数量少于20个,就从生产者那里拿过来一个
            producenumber++;
            System.out.println(Thread.currentThread().getName()+"生产了第"+producenumber+"个产品");
            notify();//已经从生产者那里拿过来一个产品了,说明手里肯定是有产品的,店员可以让消费者拿走产品了
        }else{
            try {
                wait();//店员手里产品数量多于20个,停止从生产者那里拿走产品
            } catch (InterruptedException e) {
                System.out.println(e.getMessage());
            }
        }
    }
    public synchronized void removeProduce(){//锁是clerk,相当于四个线程一个一个的执行
        if(producenumber>0){//店员手里产品数量多余0个,就让消费者拿走产品
            System.out.println(Thread.currentThread().getName()+"消费了第"+producenumber+"个产品");
            producenumber--;
            notify();//已经让消费者拿走了一个产品,说明柜台肯定有位置放产品,店员可以从生产者那里取产品了
        }else{
            try {
                wait();//店员手里产品数量少于0个,停止让消费者拿走产品
            } catch (InterruptedException e) {
                System.out.println(e.getMessage());
            }
        }
    }
}

测试类:

public class ThreadCommunicationTest {
    public static void main(String[] args) {
        Clerk clerk=new Clerk();

        Producter p=new Producter(clerk);
        Thread tp1=new Thread(p);
        tp1.setName("生产者1");
        tp1.start();
        Thread tp2=new Thread(p);
        tp2.setName("生产者2");
        tp2.start();

        Consummer c=new Consummer(clerk);
        Thread tc1=new Thread(c);
        tc1.setName("消费者1");
        tc1.start();
        Thread tc2=new Thread(c);
        tc2.setName("消费者2");
        tc2.start();
    }
}

Attention:

一共有四个线程:生产者1、生产者2、消费者1、消费者2

生产者1和生产者2线程开启后,调用Producter类里的run方法,又在run方法里调用Clerk类里的getProduce方法

相当于生产者1和生产者2反复执行的是getProduce方法

生产者1和生产者2线程开启后,调用PConsummer类里的run方法,又在run方法里调用Clerk类里的removeProduce方法

相当于消费者1和消费者2反复执行的是removeProduce方法

而getProduce方法和removeProduce方法都是同步方法,它们都在Clerk类中定义,而Clerk类从始至终只有一个对象,所以两个同步方法的锁是同一把,即Clerk类的实例对象clerk

意味着在两个方法中,四个线程只能一个一个的执行,因此线程安全

执行截图:

 

  • 4
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
生产者消费者问题是一种经典的多线程同步问题,主要涉及到生产者消费者之间的数据交换和同步。 在Java,可以使用多种方式来实现生产者消费者问题的解决方案,其最常用的方式是使用wait()和notify()方法来实现线程间的同步。 下面是一个简单的示例,演示了如何使用wait()和notify()方法来实现生产者消费者问题的解决方案: ``` import java.util.LinkedList; import java.util.Queue; public class ProducerConsumer { private Queue<Integer> buffer = new LinkedList<>(); private final int capacity = 5; public void produce() throws InterruptedException { int value = 0; while (true) { synchronized (this) { while (buffer.size() == capacity) wait(); System.out.println("Producer produced-" + value); buffer.add(value++); notify(); Thread.sleep(1000); } } } public void consume() throws InterruptedException { while (true) { synchronized (this) { while (buffer.size() == 0) wait(); int val = buffer.poll(); System.out.println("Consumer consumed-" + val); notify(); Thread.sleep(1000); } } } } ``` 在上面的示例,ProducerConsumer类表示生产者消费者问题的解决方案。这个类有一个buffer队列,它是一个FIFO队列,用于存储生产者生产的数据。 produce()方法表示生产者的行为,它使用一个while(true)循环来不断地生产数据。在每次生产之前,它首先检查buffer队列是否已满。如果buffer队列已满,则调用wait()方法来等待消费者线程消费数据。如果buffer队列未满,则将生产的数据添加到buffer队列,并调用notify()方法通知消费者线程可以消费数据了。 consume()方法表示消费者的行为,它使用一个while(true)循环来不断地消费数据。在每次消费之前,它首先检查buffer队列是否为空。如果buffer队列为空,则调用wait()方法来等待生产者线程生产数据。如果buffer队列不为空,则从buffer队列取出一个数据,并调用notify()方法通知生产者线程可以生产数据了。 在上面的示例,使用了synchronized关键字来实现线程的同步。synchronized关键字可以确保在同一时间只有一个线程可以执行被synchronized关键字包裹的代码块。wait()方法可以让线程等待,直到被notify()方法唤醒。notify()方法可以唤醒一个等待的线程。如果有多个线程等待,则只有一个线程会被唤醒。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值