zoukankan      html  css  js  c++  java
  • 生产者和消费者之间的线程通讯wait()

    生产者与消费者,采用notify()唤醒

    package com.dwz.concurrency.chapter9;
    /**
     *     生产者和消费者之间的通信问题
    * 执行wait()之后锁被释放
    */ public class ProduceConsumerVersion4 { private final Object LOCK = new Object(); private int i = 0; private volatile boolean isProduced = false; private void produce() { synchronized(LOCK) { if(isProduced) { try { LOCK.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } else { i++; System.out.println("p->" + i); LOCK.notify(); isProduced = true; } } } private void consumer() { synchronized(LOCK) { if(isProduced) { System.out.println("c->" + i); LOCK.notify(); isProduced = false; } else { try { LOCK.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } }

    测试代码(一个生产者与一个消费者)

    public static void main(String[] args) {
            ProduceConsumerVersion4 pc = new ProduceConsumerVersion4();
            
            new Thread("P") {
                @Override
                public void run() {
                    while(true) {
                        pc.produce();
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
            
            new Thread("C") {
                @Override
                public void run() {
                    while(true) {
                        pc.consumer();
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
        }

    测试结果是线程安全的,程序正常结束

    测试代码(多个生产者与多个消费者)

    public static void main(String[] args) {
            ProduceConsumerVersion2 pc = new ProduceConsumerVersion2();
            Stream.of("P1", "P2").forEach(n -> 
                new Thread(n) {
                    @Override
                    public void run() {
                        while(true) {
                            pc.produce();
                        }
                    }
                }.start()
            );
            
            Stream.of("C1", "C2").forEach(n ->
                new Thread(n) {
                    @Override
                    public void run() {
                        while(true) {
                            pc.consumer();
                        }
                    }
                }.start()
            );
        }

    测试结果:程序不能正常结束,被阻塞

    多个生产者和多个消费者之间通信采用 notify()
    缺点:会存在所有线程都等待的问题(wait)
    分析:notify不能识别wait的身份,有可能消费者唤醒的是消费者,导致线程都blocked

    改进方法,使用notifyAll()代替notify()

    package com.dwz.concurrency.chapter9;
    
    import java.util.stream.Stream;
    
    /**
     *     多个生产者和多个消费者之间通信(线程安全版)
     */
    public class ProduceConsumerVersion3 {
        private final Object LOCK = new Object();
        private int i = 0;
        private volatile boolean isProducted = false;
        
        private void produce() {
            synchronized(LOCK) {
                if(isProducted) {
                    try {
                        LOCK.wait();
                        return;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                
                i++;
                System.out.println(Thread.currentThread().getName() + "for P->" + i);
                LOCK.notifyAll();
                isProducted = true;
            }
        }
        
        private void consumer() {
            synchronized(LOCK) {
                if(!isProducted) {
                    try {
                        LOCK.wait();
                        return;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                
                System.out.println(Thread.currentThread().getName() + "for C->" + i);
                LOCK.notifyAll();
                isProducted = false;
            }
        }
    }

    测试结果,程序是线程安全的,正常执行

    The difference of sleep and wait

    1.sleep is the method of Thread, but wait is the method of Object
    2.sleep will not release the object monitor(Lock), but the wait will be release the monitor and add to the Object monitor waiting queue
    3.use sleep not need depend on monitor, but wait need
    4.The sleep method not need be wakeup, but wait method need.(besides wait(milons))

  • 相关阅读:
    对pg_latch.c 的来源探索
    对PostgreSQL的执行计划的初步学习
    21个css和Ajax表格
    23种设计模式有趣诠释
    Spket IDE, Ext开发人员的紫色匕首~
    Sql Server 2008 Reporting Services系列(一)
    C#积累(二)——ASP.NET的Session会加锁
    在TSQL语句中访问远程数据库(openrowset/opendatasource/openquery)
    ASP.NET视图的保存与加载解析(一)——视图的保存
    C#积累(一)——扩展方法就近原则和匿名类型的成员探讨
  • 原文地址:https://www.cnblogs.com/zheaven/p/12066459.html
Copyright © 2011-2022 走看看