• Java入门到精通——基础篇之多线程实现简单的PV操作的进程同步


     

    Java入门到精通——基础篇之多线程实现简单的PV操作的进程同步

    一、概述
        PV操作是对信号量进行的操作。

        进程同步是指在并发进程之间存在一种制约关系,一个进程的执行依赖另一个进程的消息,当一个进程没有得到另一个进程的消息时应等待,直到消息到达才被唤醒。举例:就像消费者与生产者的关系,说吃馒头把有一个碗能盛下6个馒头,厨师不停的生产馒头,顾客不停的吃馒头,此时厨师与顾客的关系就是同步。(如下图)

        

        下面我就为大家利用java多线程的代码实现这个操作的过程。

    二、代码展示。

    1、ManTou.java

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. package com.gaowei.PV;  
    2.   
    3. public class ManTou {  
    4.   
    5.     int id;   
    6.     ManTou(int id) {  
    7.         this.id = id;  
    8.     }  
    9.     public String toString() {  
    10.         return "ManTou : " + id;  
    11.     }  
    12. }  


    2、厨师类Pclient.java

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. package com.gaowei.PV;  
    2.   
    3. public class PClient implements Runnable {  
    4.   
    5.     private SyncStack ss=null;  
    6.     public PClient(SyncStack ss){  
    7.         this.ss=ss;  
    8.     }  
    9.     @Override  
    10.     public void run() {  
    11.         for (int i = 0; i < 20; i++) {  
    12.             ManTou mt=new ManTou(i);  
    13.             ss.push(mt);  
    14.             System.out.println("生产了:"+mt);  
    15.             try {  
    16.                 Thread.sleep(1000);  
    17.             } catch (InterruptedException e) {  
    18.                 e.printStackTrace();  
    19.             }  
    20.         }  
    21.   
    22.     }  
    23.   
    24. }  


    3、顾客类Vclient.java

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. package com.gaowei.PV;  
    2.   
    3. public class VClient implements Runnable {  
    4.     private SyncStack ss=null;  
    5.     public VClient(SyncStack ss){  
    6.         this.ss=ss;  
    7.     }  
    8.     @Override  
    9.     public void run() {  
    10.         for(int i=0; i<20; i++) {  
    11.             ManTou mt = ss.pop();  
    12.             System.out.println("消费了: " + mt);  
    13.             try {  
    14.                 Thread.sleep(6000);  
    15.             } catch (InterruptedException e) {  
    16.                 e.printStackTrace();  
    17.             }         
    18.         }  
    19.     }  
    20.   
    21. }  


    4、碗类SyncStack.java

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. package com.gaowei.PV;  
    2.   
    3. public class SyncStack {  
    4.         private int index=0;  
    5.         ManTou[] arrMT=new ManTou[6];  
    6.           
    7.         //添加馒头  
    8.         public synchronized void push(ManTou mt){  
    9.             while (index==arrMT.length) {  
    10.             try {  
    11.                 this.wait();  
    12.             } catch (InterruptedException e) {  
    13.                 e.printStackTrace();  
    14.             }  
    15.                   
    16.             }  
    17.             this.notifyAll();  
    18.             arrMT[index]=mt;  
    19.             index++;  
    20.         }  
    21.           
    22.           
    23.         //吃馒头  
    24.         public synchronized  ManTou pop(){  
    25.             while(index==0){  
    26.                 try {  
    27.                     this.wait();  
    28.                 } catch (InterruptedException e) {  
    29.                     e.printStackTrace();  
    30.                 }  
    31.             }  
    32.             this.notifyAll();  
    33.             index--;  
    34.             return arrMT[index];  
    35.         }  
    36. }  


    5、客户端显示效果代码PVClient.java

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. package com.gaowei.PV;  
    2.   
    3. public class PVClient {  
    4.   
    5.     public static void main(String[] args) {  
    6.           
    7.         SyncStack ss = new SyncStack();  
    8.         PClient p = new PClient(ss);  
    9.         VClient v= new VClient(ss);  
    10.       
    11.         new Thread(p).start();  
    12.         new Thread(v).start();  
    13.     }  
    14.   
    15. }  


    6、效果图


        由于顾客吃馒头慢要6s吃个馒头,而厨师做馒头快1s就能做一个馒头所以从图中的分布大家就可以发现厨师做到了第6个馒头了消费者才吃了1个馒头接下来由于碗中只能盛下6个馒头所以厨师只有等着顾客吃一个然后在放一个馒头到碗里,一直到最后厨师20个馒头做完了顾客还得继续把剩下的6个馒头吃完才能结束。

    三、总结。

        利用多线程实现了PV操作了接下了就要思考一下PV操作的好处在哪里?在实现代码的过程中说一个细节问题当顾客吃了一个馒头之后就会通知厨师这个线程来生产馒头,厨师生产一个馒头也会去通知顾客来吃馒头。这样的思路就和观察者思路差不多能解决生产者与消费者的耦合。说高大上点就是生产者干自己的事情,消费者干自己的事情,通过碗中消息来通知生产者该干嘛,消费者该干嘛。这样的话就把生产者和消费者的关系解耦了。

    本文转自:http://blog.csdn.net/gwblue/article/details/44515931

  • 相关阅读:
    web前端开发面试被虐篇(一)
    JSON字符串 拼接与解析
    IntelliJ IDEA 2017 Dubbo Elastic-job Redis Zookeeper RabbitMQ FastDFS MyCat 简介以及部分实现(三)
    IntelliJ IDEA 2017 MySQL5 绿色版 Spring 4 Mybatis 3 配置步骤详解(二)
    IntelliJ IDEA 2017 JDK Tomcat Maven 配置步骤详解(一)
    简单练习
    C#实现上传/下载Excel文档
    javascript练习题
    转 浏览器滚动条以及常用样式汇总
    深入基础(五)工具模块,常用模块(2)
  • 原文地址:https://www.cnblogs.com/Rozdy/p/4449390.html
Copyright © 2020-2023  润新知