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() 即可。

  • 相关阅读:
    P4387 P4387 【深基15.习9】验证栈序列
    P1241 括号序列题解
    P2058 海港题解
    P1540 机器翻译题解
    leaflet + react + typescript
    TypeScript中文手册:从 JavaScript 迁移到 TypeScript
    react-esri-leaflet与typescript
    TypeError: Super expression must either be null or a function
    前端库(gis前端库和普通库分开)
    react-leaflet:Module parse failed: Unexpected token (10:41)
  • 原文地址:https://www.cnblogs.com/lkc9/p/12521091.html
Copyright © 2011-2022 走看看