• 6.21Java多线程并发管程法


    6.21Java多线程并发管程法

    核心:

    缓冲区

    模型分析

    • 生产者--->多线程(有多个操作)

    • 消费者--->多线程

    • 缓冲区--->并发容器(JUC包下已经提供了)--->操作商品

    功能

    • 缓冲区需要实现什么功能

    • 需要并发什么操作

      • 并发存--->什么时候可以存(容器不够时,需要等待)

      • 并发取--->什么时候可以取(里面有数据,就可以取。空容器,进行等待。等待生产)

    wait同样是阻塞的一种,但是会释放锁。

    当notify或者notifyAll被调用的时候线程就进入了可运行状态

    有资源的锁定和数组越界问题
    package iostudy.threadcooperation;

    import java.util.stream.Stream;

    /**
    * 协作模型:生产者---消费者方式一:
    * 管程法
    * @since JDK 1.8
    * @date 2021/6/21
    * @author Lucifer
    */
    public class CoTestNo1 {
       public static void main(String[] args) {

           /*先创建缓冲区*/
           SynContainer container = new SynContainer();

           /*生产者*/
           new Productor(container).start();

           /*消费者*/
           new Consumer(container).start();
      }
    }

    /**
    * 多线程生产者
    */
    class Productor extends Thread{

       /*对缓冲区进行操作*/
       SynContainer container;

       /*添加构造器*/
       public Productor(SynContainer container){
           super();
           this.container = container;
      }

       /*重写run方法*/
       @Override
       public void run(){

           /*开始生产的线程代码*/
           for (int i=0; i<100; i++){
               System.out.println("生产--->" + i + "个馒头");
               container.push(new Streamedbun(i));
          }
      }
    }

    /**
    * 多线程消费者
    */
    class Consumer extends Thread{

       /*对缓冲区进行操作*/
       SynContainer container;

       /*添加构造器*/
       public Consumer(SynContainer container){
           super();
           this.container = container;
      }

       /*重写run方法*/
       @Override
       public void run(){

           /*开始生产的线程代码*/
           for (int i=0; i<100; i++){
               System.out.println("消费--->" + container.pop().id + "个馒头");
          }
      }
    }

    /**
    * 中间的缓冲区
    */
    class SynContainer{

       /*缓冲区当中要操作数据的容器--->数组*/
       Streamedbun[] buns = new Streamedbun[10]; //存储数据的容器
       int count = 0; // 计数器
       /*
       如果只是单纯的不加入并发写下面的方法还是会出现数组越界的问题
       解决办法是加入并发synchronized
        */

       //存储方法
       public synchronized void push(Streamedbun bun){

           /*buns数字赋值*/
           buns[count] = bun;
           count++;
      }

       //获取数据--->进栈原则,从最后一个位置去拿
       public synchronized Streamedbun pop(){

           /*拿出来数量就减少*/
           count--;
           Streamedbun bun = buns[count];

           /*返回数组*/
           return bun;

      }
    }

    /**
    * 数据
    */
    class Streamedbun{

       /*数据*/
       int id;

       /*构造器*/
       public Streamedbun(int id){
           this.id = id;
      }
    }
    解决了数组越界问题和
    package iostudy.threadcooperation;

    import java.util.stream.Stream;

    /**
    * 协作模型:生产者---消费者方式一:
    * 管程法
    * 借助缓冲区实现
    * @since JDK 1.8
    * @date 2021/6/21
    * @author Lucifer
    */
    public class CoTestNo1 {
       public static void main(String[] args) {

           /*先创建缓冲区*/
           SynContainer container = new SynContainer();

           /*生产者*/
           new Productor(container).start();

           /*消费者*/
           new Consumer(container).start();
      }
    }

    /**
    * 多线程生产者
    */
    class Productor extends Thread{

       /*对缓冲区进行操作*/
       SynContainer container;

       /*添加构造器*/
       public Productor(SynContainer container){
           super();
           this.container = container;
      }

       /*重写run方法*/
       @Override
       public void run(){

           /*开始生产的线程代码*/
           for (int i=0; i<100; i++){
               System.out.println("生产--->" + i + "个馒头");
               container.push(new Streamedbun(i));
          }
      }
    }

    /**
    * 多线程消费者
    */
    class Consumer extends Thread{

       /*对缓冲区进行操作*/
       SynContainer container;

       /*添加构造器*/
       public Consumer(SynContainer container){
           super();
           this.container = container;
      }

       /*重写run方法*/
       @Override
       public void run(){

           /*开始生产的线程代码*/
           for (int i=0; i<100; i++){
               System.out.println("消费--->" + container.pop().id + "个馒头");
          }
      }
    }

    /**
    * 中间的缓冲区
    */
    class SynContainer{

       /*缓冲区当中要操作数据的容器--->数组*/
       Streamedbun[] buns = new Streamedbun[10]; //存储数据的容器
       int count = 0; // 计数器
       /*
       如果只是单纯的不加入并发写下面的方法还是会出现数组越界的问题
       解决办法是加入并发synchronized--->这样就保证了缓冲区符合生产者、消费者模型的需求:有线程则无法在添加线程
       如何保证数据的准确性?
       只需要控制何时能消费:--->容器中是否存在数据。如果有数据,可以消费
       如果没有数据:--->等待
       如何判断?
       查看计数器是否为0
        */

       //存储方法
       public synchronized void push(Streamedbun bun){

           /*判断何时能生产--->容器存在空间--->size==0*/
           if (count==buns.length){

               /*此时不能生产,只能等待*/
               try {
                   this.wait(); //线程阻塞--->消费者通知生产,接触等待
              }catch (InterruptedException e){
                   System.out.println(e.getMessage());
                   e.printStackTrace();
              }

          }

           /*buns数字赋值*/
           buns[count] = bun;
           count++;
           /*通知消费者消费*/
           this.notifyAll();

      }

       //获取数据--->进栈原则,从最后一个位置去拿
       public synchronized Streamedbun pop(){

           /*判断何时进行获取数据的操作*/
           if (count==0){

               /*没有数据,只有等待*/
               //每个对象里面都有一个wait方法
               try {
                   this.wait(); //此时:线程阻塞--->生产者通知消费,解除阻塞--->会释放锁
              }catch (InterruptedException e){
                   System.out.println(e.getMessage());
                   e.printStackTrace();
              }

          }

           /*拿出来数量就减少*/
           count--;
           Streamedbun bun = buns[count];
           /*消费完成通知生产者*/
           this.notifyAll(); //存在空间了,可以唤醒对方生产了

           /*返回数组*/
           return bun;

      }
    }

    /**
    * 数据
    */
    class Streamedbun{

       /*数据*/
       int id;

       /*构造器*/
       public Streamedbun(int id){
           this.id = id;
      }
    }

     

    It's a lonely road!!!
  • 相关阅读:
    java:输出流程printStream
    phalcon 连接多个数据库 phalcon multi-database
    Selenium Webdriver元素定位的八种常用方法
    adb push ,adb pull和adb install的区别
    Java将数据写进excel
    Java接口和抽象类的区别
    深入理解Java的接口和抽象类
    Java内存解析 程序的执行过程
    bit,byte,char,位,字节,字符 的区别
    java static成员变量方法和非static成员变量方法的区别 ( 二 )
  • 原文地址:https://www.cnblogs.com/JunkingBoy/p/14915360.html
Copyright © 2020-2023  润新知