zoukankan      html  css  js  c++  java
  • 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() 即可。

  • 相关阅读:
    用到了yii2 hasMany() 方法,一对多关联
    jquery操作select标签change事件
    Yii2如何批量添加数据
    [bzoj1497][NOI2006]最大获利
    [bzoj]2962序列操作
    洛谷 P1350 车的放置
    洛谷 P1142 轰炸
    初级数论练习题
    洛谷 P3795 钟氏映射
    洛谷 2953 [USACO09OPEN]牛的数字游戏Cow Digit Game
  • 原文地址:https://www.cnblogs.com/lkc9/p/12521091.html
Copyright © 2011-2022 走看看