认识多线程(三)、消费者和生产者

113 阅读3分钟

认识多线程(三)、消费者和生产者

一、认识消费者和生产者

多线程生产者消费者模式是一种常见的并发编程模式,用于解决生产者和消费者之间的协作问题。在这种模式中,生产者负责生成数据或任务,并将其提交到共享的缓冲区中,而消费者则负责从缓冲区中获取数据或任务并进行处理。

这种模式可以应用于各种场景,比如生产者生成任务,消费者执行任务;生产者生成数据,消费者对数据进行处理等。

在这样的模式下,我们通常会面临以下挑战:

  1. 生产者和消费者之间的同步:需要确保在多线程环境下生产者和消费者之间的数据交换是安全可靠的。
  2. 缓冲区管理:需要一个合适的缓冲区来存放生产者生成的数据,以供消费者使用。
  3. 避免过度生产或消费:需要避免生产者生成过多的数据导致缓冲区溢出,或者消费者处理速度过慢导致缓冲区耗尽。

为了解决这些挑战,我们可以利用Java中的并发工具来实现生产者消费者模式,比如使用BlockingQueue作为缓冲区,利用synchronized关键字或者ReentrantLock来进行同步控制,使用wait()notify()或者Condition来实现线程间的通信等。

另外,Java 5引入的java.util.concurrent包中提供了一系列专门用于多线程编程的工具类,比如ThreadPoolExecutorSemaphoreCountDownLatch等,这些工具类可以帮助我们更方便地实现生产者消费者模式。

二、实现简单消费模型

认识线程wait()函数和notify()函数

在Java中,wait()notify()notifyAll()方法通常用于协调多线程的执行。这些方法都是Object类的方法,因此可以在任何对象上调用。然而,只有在同步上下文中才能安全地使用它们。

这是这些方法的基本概念:

  1. wait(): 此方法使当前线程等待,直到另一个线程调用该对象的notify()notifyAll()方法。如果在调用wait()时,锁未被当前线程持有,则会发生IllegalMonitorStateException。为了避免这种情况,我们通常在同步块或方法中调用wait()方法。
  2. notify(): 此方法唤醒在此对象上等待的单个线程。如果没有线程正在等待,则此方法不会有任何效果。如果多个线程正在等待,则其中一个线程会被选择并唤醒。选择哪个线程是不确定的。
  3. notifyAll(): 此方法唤醒在此对象上等待的所有线程。如果没有线程正在等待,则此方法不会有任何效果。

这些方法通常用于实现生产者-消费者模式,当生产者生产一个新项目时,它会通知消费者,然后消费者会消费这个项目。

package com.example.mayikttest.Thread.ConsumerPro;

public class Thread4 {
    /**
     * 公共类
     */
    class Res{
        private String name;
        private String sex;

        private boolean flag = false;
    }

    // 生产线程
    public class InputThread extends Thread{
        private Res res;
        public InputThread(Res res) {
            this.res = res;
        }
        @Override
        public void run() {
            int count  = 0;
            while(true){
                synchronized (res){
                    if(res.flag){
                        try {
                            res.wait();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    if(count % 2 == 0){
                        res.name = "小张";
                        res.sex = "男";
                    }else{
                        res.name = "小美";
                        res.sex = "女";
                    }
                    Res ress = res;
                    count = (count + 1) % 2;
                    res.flag= true;
                    res.notify();
                }
            }
        }
    }

    // 消费线程
    class OutputThread extends Thread{
        private Res res;

        public OutputThread(Res res) {
            this.res = res;
        }

        @Override
        public void run() {
            while (true){
                synchronized (res){
                    if(!res.flag){
                        try {
                            res.wait();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    System.out.println("姓名:" + res.name + "  " + "性别:" + res.sex);
                    res.flag= false;
                    res.notify();
                }
            }
        }
    }

    public void print(){
        Res res = new Res();
        InputThread inputThread = new InputThread(res);
        OutputThread outputThread = new OutputThread(res);
        inputThread.start();
        outputThread.start();
    }
    public static void main(String[] args) {
        new Thread4().print();
    }

}