Java多线程-生产者/消费者模式实现

Posted Alan Lau

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java多线程-生产者/消费者模式实现相关的知识,希望对你有一定的参考价值。

单生产者与单消费者

示例:

public class ProduceConsume {
        public static void main(String[] args) {
            String lock = new String("");
            Produce produce = new Produce(lock);
            Consume consume = new Consume(lock);

            new Thread(() -> {
                while (true) {
                    produce.setValue();
                }
            }, "ProductThread").start();
            new Thread(() -> {
                while (true) {
                    consume.getValue();
                }
            }, "ConsumeThread").start();
        }

        /**
         * 生产者
         */
        static class Produce {
            private String lock;

            public Produce(String lock) {
                this.lock = lock;
            }

            public void setValue() {
                try {
                    synchronized (lock) {
                        if (!ValueObject.value.equals("")) {
                            lock.wait();
                        }
                        String value = System.currentTimeMillis() + "_" + System.nanoTime();
                        System.out.println("set的值是" + value);
                        ValueObject.value = value;
                        lock.notify();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        /**
         * 消费者
         */
        static class Consume {
            private String lock;

            public Consume(String lock) {
                this.lock = lock;
            }

            public void getValue() {
                try {
                    synchronized (lock) {
                        if (ValueObject.value.equals("")) {
                            lock.wait();
                        }
                        System.out.println("get的值是" + ValueObject.value);
                        ValueObject.value = "";
                        lock.notify();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        static class ValueObject {
            public static String value = "";
        }
}

执行结果如下:

 

 

多生产者与多消费者

这种模式下,容易出现“假死”,也就是全部线程都进入了 WAITNG 状态,程序不在执行任何业务功能了,整个项目呈停止状态。

示例:

public class MultiProduceConsume {
    public static void main(String[] args) throws InterruptedException {
        String lock = new String("");
        Produce produce = new Produce(lock);
        Consume consume = new Consume(lock);
        Thread[] pThread = new Thread[2];
        Thread[] cThread = new Thread[2];
        for (int i = 0; i < 2; i++) {
            pThread[i] = new Thread(() -> {
                while (true) {
                    produce.setValue();
                }
            }, "生产者" + (i + 1));

            cThread[i] = new Thread(() -> {
                while (true) {
                    consume.getValue();
                }
            }, "消费者" + (i + 1));
            pThread[i].start();
            cThread[i].start();
        }

        Thread.sleep(5000);
        Thread[] threadArray = new Thread[Thread.currentThread().getThreadGroup().activeCount()];
        Thread.currentThread().getThreadGroup().enumerate(threadArray);
        for (int i = 0; i < threadArray.length; i++) {
            System.out.println(threadArray[i].getName() + " " + threadArray[i].getState());
        }
    }

    static class Produce {
        private String lock;

        public Produce(String lock) {
            this.lock = lock;
        }

        public void setValue() {
            try {
                synchronized (lock) {
                    while(!ValueObject.value.equals("")) {
                        System.out.println("生产者 " + Thread.currentThread().getName() + " WAITING了⭐");
                        lock.wait();
                    }
                    System.out.println("生产者 " + Thread.currentThread().getName() + " RUNNABLE了");
                    String value = System.currentTimeMillis() + "_" + System.nanoTime();
                    ValueObject.value = value;
                    lock.notify();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    static class Consume {
        private String lock;

        public Consume(String lock) {
            this.lock = lock;
        }

        public void getValue() {
            try {
                synchronized (lock) {
                    while (ValueObject.value.equals("")) {
                        System.out.println("消费者 " + Thread.currentThread().getName() + " WAITING了⭐");
                        lock.wait();
                    }
                    System.out.println("消费者 " + Thread.currentThread().getName() + "RUNNABLE了");
                    ValueObject.value = "";
                    lock.notify();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    static class ValueObject {
        public static String value = "";
    }
}

运行结果如图:

 

分析:

虽然代码中通过 wait/notify 进行通信了,但是不能保证 notify 唤醒的一定是异类,也可能是同类,比如“生产者”唤醒了“生产者”这样的情况。

解决方案:

假死出现的主要原因是有可能连续唤醒了同类。所以解决方案很简单,就是把 notify() 改为 notifyAll() 即可。

以上是关于Java多线程-生产者/消费者模式实现的主要内容,如果未能解决你的问题,请参考以下文章

java 多线程并发系列之 生产者消费者模式的两种实现

Java多线程-生产者/消费者模式实现

java 多线程 22 :生产者/消费者模式 进阶 利用await()/signal()实现

java中的多线程的实现生产者消费者模式

java线程之间通信,多种方式实现生产者消费者模式

Java多线程-----实现生产者消费者模式的几种方式