JAVA多线程(九)Java多线程之生产者与消费者

1.JAVA多线程(九)Java多线程之生产者与消费者

  • 需求如下:自定义多线程生产者与消费者
  • 1.如果生产者没有生产消息,就需要去生产消息,消费者就需要等待消费者生产完以后再去消费。
  • 2.如果消费者没有消费消息,那么生产者就需要等待,消费都消费完成后,再去生产消息。

1.1 生产者与消费者【一个生产线程和一个消费者线程】

package com.yuanxw.chapter9;
/**
 * 自定义多线程生产者与消费者
 * 1.如果生产者没有生产消息,就需要去生产消息,消费者就需要等待消费者生产完以后再去消费。
 * 2.如果消费者没有消费消息,那么生产者就需要等待,消费都消费完成后,再去生产消息。
 */
public class ProduceConsumer {
    /** 生产数量 **/
    private int num = 0;
    /** 锁 **/
    protected final Object LOCK = new Object();
    /** volatile:内存可见性关键字,默认为没有生产,可以进行生产 **/
    private volatile boolean isProducted = false;

    /**
     * 生产方法
     * @return
     */
    public void produce() throws InterruptedException {
        // 同步生产
        synchronized (LOCK){
            // 如果消息已经生产,需要等待消费者消费后再去生产
            if(isProducted){
                /**
                 * 调用 wait() 使得线程等待某个条件满足,线程在等待时会被挂起,当其他线程的运行使得这个条件满足时,其它线程会调用 notify() 或者 notifyAll() 来唤醒挂起的线程。
                 * 它们都属于 Object 的一部分,而不属于 Thread。
                 */
                LOCK.wait();
            }else {
                // 如果已经消费,那么就需要进行生产
                num++;
                System.out.println(String.format("生产消息>>【%s】", num));
                /**
                 * 调用 wait() 使得线程等待某个条件满足,线程在等待时会被挂起,当其他线程的运行使得这个条件满足时,其它线程会调用 notify() 或者 notifyAll() 来唤醒挂起的线程。
                 * 它们都属于 Object 的一部分,而不属于 Thread。
                 */
                // 通知消费者,可以进行消费
                LOCK.notify();
                // 设置标记:已经生产
                isProducted = true;
            }
        }
    }

    /**
     * 消费方法
     */
    public void consumer() throws InterruptedException {
        // 同步消费
        synchronized (LOCK){
            // 如果已经生产,那么消费者消费
            if(isProducted){
                System.out.println(String.format("消费消息<<【%s】", num));
                // 通知生产者已经消费
                LOCK.notify();
                // 设置标记:未生产
                isProducted = false;
            }else {
                // 如果已经没有生产,即需要消息费进行等待生产者进行生产
                LOCK.wait();
            }
        }
    }


    public static void main(String[] args) {
        ProduceConsumer produceConsumer = new ProduceConsumer();
        // 生产者:生产线程
        new Thread(()->{
            try {
                while (true) {
                    produceConsumer.produce();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        // 消费者:消费线程
        new Thread(()->{
            try {
                while (true) {
                    produceConsumer.consumer();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

执行结果:

生产消息>>【1】
消费消息<<【1】
生产消息>>【2】
消费消息<<【2】
生产消息>>【3】
消费消息<<【3】
生产消息>>【4】
消费消息<<【4】
生产消息>>【5】
消费消息<<【5】
生产消息>>【6】
消费消息<<【6】
生产消息>>【7】
消费消息<<【7】
生产消息>>【8】
消费消息<<【8】
生产消息>>【9】
消费消息<<【9】
生产消息>>【10】
消费消息<<【10】

1.2 生产者与消费者【多个生产线程和多个消费者线程】

package com.yuanxw.chapter9;
import java.util.Arrays;
/**
 * 自定义多线程生产者与消费者【多生產者多消費者】
 * 1.如果生产者没有生产消息,就需要去生产消息,消费者就需要等待消费者生产完以后再去消费。
 * 2.如果消费者没有消费消息,那么生产者就需要等待,消费都消费完成后,再去生产消息。
 */
public class MultiProduceConsumer {
    /** 生产数量 **/
    private int num = 0;
    /** 锁 **/
    protected final Object LOCK = new Object();
    /** volatile:内存可见性关键字,默认为没有生产,可以进行生产 **/
    private volatile boolean isProducted = false;

    /**
     * 生产方法
     * @return
     */
    public void produce() throws InterruptedException {
        // 同步生产
        synchronized (LOCK){
            // 如果消息已经生产,需要等待消费者消费后再去生产
            while (isProducted){
                /**
                 * 调用 wait() 使得线程等待某个条件满足,线程在等待时会被挂起,当其他线程的运行使得这个条件满足时,其它线程会调用 notify() 或者 notifyAll() 来唤醒挂起的线程。
                 * 它们都属于 Object 的一部分,而不属于 Thread。
                 */
                LOCK.wait();
            }
            // 如果已经消费,那么就需要进行生产
            num++;
            System.out.println(String.format("生产消息>>>>【%s】", num));
            /**
             * 调用 wait() 使得线程等待某个条件满足,线程在等待时会被挂起,当其他线程的运行使得这个条件满足时,其它线程会调用 notify() 或者 notifyAll() 来唤醒挂起的线程。
             * 它们都属于 Object 的一部分,而不属于 Thread。
             */
            // 通知消费者,可以进行消费
            LOCK.notifyAll();
            // 设置标记:已经生产
            isProducted = true;
        }
    }

    /**
     * 消费方法
     */
    public void consumer() throws InterruptedException {
        // 同步消费
        synchronized (LOCK){
            // 如果已经生产,那么消费者消费
            while (!isProducted){
                // 如果已经没有生产,即需要消息费进行等待生产者进行生产
                LOCK.wait();
            }
            System.out.println(String.format("消费消息<<<<【%s】", num));
            // 通知生产者已经消费
            LOCK.notifyAll();
            // 设置标记:未生产
            isProducted = false;
        }
    }


    public static void main(String[] args) {
        MultiProduceConsumer produceConsumer = new MultiProduceConsumer();
        Arrays.asList("Produce1","Produce2","Produce3","Produce4","Produce5","Produce6","Produce7","Produce8").forEach(p->{
            // 生产者Produce
            new Thread(()->{
                try {
                    while (true) {
                        produceConsumer.produce();
                         Thread.sleep(10L);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            },p).start();
        });

        Arrays.asList("Consumer1","Consumer2","Consumer3","Consumer4","Consumer5","Consumer6").forEach(c-> {
            // 消费者
            new Thread(() -> {
                try {
                    while (true) {
                        produceConsumer.consumer();
                         Thread.sleep(10L);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            },c).start();
        });
    }
}

执行结果:

生产消息>>>>【1】
消费消息<<<<【1】
生产消息>>>>【2】
消费消息<<<<【2】
生产消息>>>>【3】
消费消息<<<<【3】
生产消息>>>>【4】
消费消息<<<<【4】
生产消息>>>>【5】
消费消息<<<<【5】
生产消息>>>>【6】
消费消息<<<<【6】
生产消息>>>>【7】
消费消息<<<<【7】
生产消息>>>>【8】
消费消息<<<<【8】
生产消息>>>>【9】
消费消息<<<<【9】
生产消息>>>>【10】
消费消息<<<<【10】
生产消息>>>>【11】
消费消息<<<<【11】
生产消息>>>>【12】
消费消息<<<<【12】
生产消息>>>>【13】
消费消息<<<<【13】
生产消息>>>>【14】
消费消息<<<<【14】
生产消息>>>>【15】
消费消息<<<<【15】
生产消息>>>>【16】
消费消息<<<<【16】
生产消息>>>>【17】
消费消息<<<<【17】
生产消息>>>>【18】
消费消息<<<<【18】
生产消息>>>>【19】
消费消息<<<<【19】
生产消息>>>>【20】
消费消息<<<<【20】

1.3 JAVA中sleep() 方法和 wait() 方法区别

  • sleep方法是Thread类的方法,而wait方法是Object方法。
  • sleep方法没有释放锁,而wait方法释放了锁,并且加入到Object的queue。
  • 使用sleep方法不用synchronized监控,而wait方法需要。
  • 使用sleep方法不需要唤醒,而wait需要。

    – 以上为《JAVA多线程(九)Java多线程之生产者与消费者》,如有不当之处请指出,我后续逐步完善更正,大家共同提高。谢谢大家对我的关注。

——厚积薄发(yuanxw)

你可能感兴趣的:(#,JAVA多线程)