zoukankan      html  css  js  c++  java
  • Java学习之线程通信(多线程(synchronized))--生产者消费者

    分析线程经典案例生产者消费者

     1 /**
     2 共享数据
     3 */
     4 class Resource
     5 {
     6     private String name;
     7     private int count=1;
     8     private boolean flag=false;
     9     
    10     public synchronized void set(String name)
    11     {    
    12         if(flag)
    13             try{this.wait();}catch(InterruptedException e){}
    14         this.name=name+count;
    15         count++;
    16         System.out.println(Thread.currentThread().getName() + "...生产者..." + this.name);
    17         flag = true;
    18         notify();
    19     }
    20     
    21     public synchronized void out() 
    22     {
    23         if(!flag)
    24             try{this.wait();}catch(InterruptedException e){}
    25         System.out.println(Thread.currentThread().getName() + "==消费者==" + this.name);
    26         flag = false;
    27         notify();
    28     }
    29 }
    30 
    31 //定义线程任务(生产者线程)
    32 class Producer implements Runnable
    33 {
    34     private Resource r;
    35     
    36     Producer(Resource r)
    37     {
    38         this.r=r;
    39     }
    40     public void run()
    41     {
    42         while(true)
    43         {
    44             r.set("商品");
    45         }
    46     }
    47 }
    48 //定义线程任务(消费者线程)
    49 class Consumer implements Runnable
    50 {
    51     private Resource r;
    52     
    53     Consumer(Resource r)
    54     {
    55         this.r=r;
    56     }
    57     
    58     public void run()
    59     {
    60         while(true)
    61         {
    62             r.out();
    63         }
    64     }
    65 }
    66 
    67 class ProducerConsumerDemo
    68 {
    69     public static void main(String[] args)
    70     {
    71         //实例化共享资源
    72         Resource r = new Resource();
    73         //实例化线程任务,指定共享资源
    74         Producer p=new Producer(r);
    75         Consumer c=new Consumer(r);
    76         //实例化线程,指定线程任务
    77         Thread t0=new Thread(p);
    78         Thread t1=new Thread(p);
    79         Thread t2=new Thread(c);
    80         Thread t3=new Thread(c);
    81         //开启线程,执行线程任务中的run方法
    82         t0.start();
    83         t1.start();
    84         t2.start();
    85         t3.start();
    86     }
    87 }

    运行结果:

    结果分析:

    那么怎么再判断flag呢?while

    代码如下:

     1 class Resource
     2 {
     3     private String name;
     4     private int count=1;
     5     private boolean flag=false;
     6     
     7     public synchronized void set(String name) // 有两个线程t0 t1
     8     {    
     9         while(flag)
    10             try{this.wait();}catch(InterruptedException e){}
    11         this.name=name+count;
    12         count++;
    13         System.out.println(Thread.currentThread().getName() + "...生产者..." + this.name);
    14         flag = true;
    15         notify();
    16     }
    17     
    18     public synchronized void out() // 有两个线程t2 t3
    19     {
    20         while(!flag)
    21             try{this.wait();}catch(InterruptedException e){}
    22         System.out.println(Thread.currentThread().getName() + "==消费者==" + this.name);
    23         flag = false;
    24         notify();
    25     }
    26 }

    结果出现死锁:

    结果分析:

    通过分析,那能不能每次唤醒只唤醒对方线程(如生产者线程只唤醒消费者线程,消费者线程只唤醒生产者线程),查看Object对象方法中没有,但是有一个notifyAll()方法,实在不行就把所有阻塞线程(相同同步锁的线程)都唤醒。

     1 class Resource
     2 {
     3     private String name;
     4     private int count=1;
     5     private boolean flag=false;
     6     
     7     public synchronized void set(String name) // 有两个线程t0 t1
     8     {    
     9         while(flag)
    10             try{this.wait();}catch(InterruptedException e){}
    11         this.name=name+count;
    12         count++;
    13         System.out.println(Thread.currentThread().getName() + "...生产者..." + this.name);
    14         flag = true;
    15         notifyAll();
    16     }
    17     
    18     public synchronized void out() // 有两个线程t2 t3
    19     {
    20         while(!flag)
    21             try{this.wait();}catch(InterruptedException e){}
    22         System.out.println(Thread.currentThread().getName() + "==消费者==" + this.name);
    23         flag = false;
    24         notifyAll();
    25     }
    26 }

    结果:

    这样就可以了。

    总结:

    if判断只能判断一次,如果执行等待方法,下次唤醒的线程获取执行权后(唤醒后的线程会从上次等待位置,向下执行)就不能再判断

    while判断解决唤醒的线程获取执行权后无法判断

    notify:只能唤醒任意一个线程,有可能会唤醒本方线程,while+notify会导致死锁

    notifyAll:解决了死锁问题

  • 相关阅读:
    VAE变分自编码器Keras实现
    使用docker快速搭建hive环境
    Spark Streaming高吞吐、高可靠的一些优化
    MySQL在同一个表上,删除查询出来的结果
    谈谈Hadoop MapReduce和Spark MR实现
    Java ThreadLocal的使用
    我能想到的最浪漫的Java网络教程之Socket,三步到位!!!
    Java中的不可变集合,我们换个方式理解!!!
    一个试图了解JVM内存模型的两年经验的初级程序员,透彻!
    异步文件通道Java NIO你需要了解多少,来看看这篇文章
  • 原文地址:https://www.cnblogs.com/WarBlog/p/12082961.html
Copyright © 2011-2022 走看看