欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java多線程 生產(chǎn)者消費(fèi)者模型實(shí)例詳解

 更新時(shí)間:2019年09月06日 09:17:01   作者:慢慢來(lái)  
這篇文章主要介紹了Java多線程 生產(chǎn)者消費(fèi)者模型實(shí)例詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

生產(chǎn)者消費(fèi)者模型

生產(chǎn)者:生產(chǎn)任務(wù)的個(gè)體;

消費(fèi)者:消費(fèi)任務(wù)的個(gè)體;

緩沖區(qū):是生產(chǎn)者和消費(fèi)者之間的媒介,對(duì)生產(chǎn)者和消費(fèi)者解耦。

當(dāng)

緩沖區(qū)元素為滿,生產(chǎn)者無(wú)法生產(chǎn),消費(fèi)者繼續(xù)消費(fèi);

緩沖區(qū)元素為空,消費(fèi)者無(wú)法消費(fèi),生產(chǎn)者繼續(xù)生產(chǎn);

wait()/notify()生產(chǎn)者消費(fèi)者模型

制作一個(gè)簡(jiǎn)單的緩沖區(qū)ValueObject,value為空表示緩沖區(qū)為空,value不為空表示緩沖區(qū)滿

public class ValueObject {
  public static String value = "";
}

生產(chǎn)者,緩沖區(qū)滿則wait(),不再生產(chǎn),等待消費(fèi)者notify(),緩沖區(qū)為空則開(kāi)始生產(chǎn)

public class Producer {
  private Object lock;

  public Producer(Object 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();
    }
  }
}

消費(fèi)者,緩沖區(qū)為空則wait(),等待生產(chǎn)者notify(),緩沖區(qū)為滿,消費(fèi)者開(kāi)始消費(fèi)

public class Customer {
  private Object lock;

  public Customer(Object 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();
    }
  }
}

main方法,啟動(dòng)一個(gè)生產(chǎn)者和一個(gè)消費(fèi)者

public class Main {
  public static void main(String[] args)
  {
    Object lock = new Object();
    final Producer producer = new Producer(lock);
    final Customer customer = new Customer(lock);
    Runnable producerRunnable = new Runnable()
    {
      public void run()
      {
        while (true)
        {
          producer.setValue();
        }
      }
    };
    Runnable customerRunnable = new Runnable()
    {
      public void run()
      {
        while (true)
        {
          customer.getValue();
        }
      }
    };
    Thread producerThread = new Thread(producerRunnable);
    Thread CustomerThread = new Thread(customerRunnable);
    producerThread.start();
    CustomerThread.start();
  }
}

運(yùn)行結(jié)果如下

Set的值是:1564733938518_27520480474279
Get的值是:1564733938518_27520480474279
Set的值是:1564733938518_27520480498378
Get的值是:1564733938518_27520480498378
Set的值是:1564733938518_27520480540254
Get的值是:1564733938518_27520480540254
······

生產(chǎn)者和消費(fèi)者交替運(yùn)行,生產(chǎn)者生產(chǎn)一個(gè)字符串,緩沖區(qū)為滿,消費(fèi)者消費(fèi)一個(gè)字符串,緩沖區(qū)為空,循環(huán)往復(fù),滿足生產(chǎn)者/消費(fèi)者模型。

await()/signal()生產(chǎn)者/消費(fèi)者模型

緩沖區(qū)

public class ValueObject {
  public static String value = "";
}

ThreadDomain48繼承ReentrantLock,set方法生產(chǎn),get方法消費(fèi)

public class ThreadDomain48 extends ReentrantLock
{
  private Condition condition = newCondition();

  public void set()
  {
    try
    {
      lock();
      while (!"".equals(ValueObject.value))
        condition.await();
      ValueObject.value = "123";
      System.out.println(Thread.currentThread().getName() + "生產(chǎn)了value, value的當(dāng)前值是" + ValueObject.value);
      condition.signal();
    }
    catch (InterruptedException e)
    {
      e.printStackTrace();
    }
    finally
    {
      unlock();
    }
  }

  public void get()
  {
    try
    {
      lock();
      while ("".equals(ValueObject.value))
        condition.await();
      ValueObject.value = "";
      System.out.println(Thread.currentThread().getName() + "消費(fèi)了value, value的當(dāng)前值是" + ValueObject.value);
      condition.signal();
    }
    catch (InterruptedException e)
    {
      e.printStackTrace();
    }
    finally
    {
      unlock();
    }
  }
}

MyThread41啟動(dòng)兩個(gè)生產(chǎn)線程和一個(gè)消費(fèi)線程

public class MyThread41 {
  public static void main(String[] args)
  {
    final ThreadDomain48 td = new ThreadDomain48();
    Runnable producerRunnable = new Runnable()
    {
      public void run()
      {
        for (int i = 0; i < Integer.MAX_VALUE; i++)
          td.set();
      }
    };
    Runnable customerRunnable = new Runnable()
    {
      public void run()
      {
        for (int i = 0; i < Integer.MAX_VALUE; i++)
          td.get();
      }
    };
    Thread ProducerThread1 = new Thread(producerRunnable);
    ProducerThread1.setName("Producer1");
    Thread ProducerThread2 = new Thread(producerRunnable);
    ProducerThread2.setName("Producer2");
    Thread ConsumerThread = new Thread(customerRunnable);
    ConsumerThread.setName("Consumer");
    ProducerThread1.start();
    ProducerThread2.start();
    ConsumerThread.start();
  }
}

輸出結(jié)果如下

Producer1生產(chǎn)了value, value的當(dāng)前值是123
Consumer消費(fèi)了value, value的當(dāng)前值是
Producer1生產(chǎn)了value, value的當(dāng)前值是123

為什么Producer2無(wú)法生產(chǎn),消費(fèi)者無(wú)法消費(fèi)呢?是因?yàn)榇藭r(shí)緩沖區(qū)為滿,Producer1的notify()應(yīng)該喚醒Consumer卻喚醒了Producer2,導(dǎo)致Producer2因?yàn)榫彌_區(qū)為滿和Consumer沒(méi)有被喚醒而處于waiting狀態(tài),此時(shí)三個(gè)線程均在等待,出現(xiàn)了假死。

解決方案有兩種:

1.讓生產(chǎn)者喚醒所有線程,在set方法中使用condition.signalAll();

2.使用兩個(gè)Condition,生產(chǎn)者Condition和消費(fèi)者Condition,喚醒指定的線程;

正常輸入如下:

······
Producer2生產(chǎn)了value, value的當(dāng)前值是123
Consumer消費(fèi)了value, value的當(dāng)前值是
Producer2生產(chǎn)了value, value的當(dāng)前值是123
Consumer消費(fèi)了value, value的當(dāng)前值是
Producer2生產(chǎn)了value, value的當(dāng)前值是123
Consumer消費(fèi)了value, value的當(dāng)前值是
Producer1生產(chǎn)了value, value的當(dāng)前值是123
Consumer消費(fèi)了value, value的當(dāng)前值是
Producer1生產(chǎn)了value, value的當(dāng)前值是123
Consumer消費(fèi)了value, value的當(dāng)前值是
Producer1生產(chǎn)了value, value的當(dāng)前值是123
Consumer消費(fèi)了value, value的當(dāng)前值是
Producer1生產(chǎn)了value, value的當(dāng)前值是123
Consumer消費(fèi)了value, value的當(dāng)前值是
Producer1生產(chǎn)了value, value的當(dāng)前值是123
Consumer消費(fèi)了value, value的當(dāng)前值是
······

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Spring?MVC各種參數(shù)進(jìn)行封裝的方法實(shí)例

    Spring?MVC各種參數(shù)進(jìn)行封裝的方法實(shí)例

    這篇文章主要給大家介紹了關(guān)于Spring?MVC各種參數(shù)進(jìn)行封裝的相關(guān)資料,SpringMVC內(nèi)置多種數(shù)據(jù)類(lèi)型轉(zhuǎn)換器,可以根據(jù)請(qǐng)求中的參數(shù)與后端控制器方法的參數(shù)的關(guān)系為我們實(shí)現(xiàn)簡(jiǎn)單的數(shù)據(jù)封裝,需要的朋友可以參考下
    2023-06-06
  • 詳解Mybatis 傳遞參數(shù)類(lèi)型為L(zhǎng)ist的取值問(wèn)題

    詳解Mybatis 傳遞參數(shù)類(lèi)型為L(zhǎng)ist的取值問(wèn)題

    這篇文章主要介紹了詳解Mybatis 傳遞參數(shù)類(lèi)型為L(zhǎng)ist的取值問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • Java使用POI將多個(gè)Sheet合并為一個(gè)Sheet

    Java使用POI將多個(gè)Sheet合并為一個(gè)Sheet

    這篇文章主要為大家詳細(xì)介紹了Java使用POI將多個(gè)Sheet合并為一個(gè)Sheet,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Java中的Static class詳解及實(shí)例代碼

    Java中的Static class詳解及實(shí)例代碼

    這篇文章主要介紹了 Java中的Static class詳解及實(shí)例代碼的相關(guān)資料,在Java中我們可以有靜態(tài)實(shí)例變量、靜態(tài)方法、靜態(tài)塊。類(lèi)也可以是靜態(tài)的,需要的朋友可以參考下
    2017-03-03
  • mybatis-plus查詢無(wú)數(shù)據(jù)問(wèn)題及解決

    mybatis-plus查詢無(wú)數(shù)據(jù)問(wèn)題及解決

    這篇文章主要介紹了mybatis-plus查詢無(wú)數(shù)據(jù)問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • SpringBoot Admin 使用指南(推薦)

    SpringBoot Admin 使用指南(推薦)

    這篇文章主要介紹了SpringBoot Admin 使用指南(推薦),Spring Boot Admin 是一個(gè)管理和監(jiān)控你的 Spring Boot 應(yīng)用程序的應(yīng)用程序,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2018-01-01
  • Spring線程池ThreadPoolExecutor配置并且得到任務(wù)執(zhí)行的結(jié)果

    Spring線程池ThreadPoolExecutor配置并且得到任務(wù)執(zhí)行的結(jié)果

    今天小編就為大家分享一篇關(guān)于Spring線程池ThreadPoolExecutor配置并且得到任務(wù)執(zhí)行的結(jié)果,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-03-03
  • JAVA提高第九篇 集合體系

    JAVA提高第九篇 集合體系

    這篇文章主要為大家詳細(xì)介紹了JAVA提高第九篇集合體系的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • SpringMVC文件上傳原理及實(shí)現(xiàn)過(guò)程解析

    SpringMVC文件上傳原理及實(shí)現(xiàn)過(guò)程解析

    這篇文章主要介紹了SpringMVC文件上傳原理及實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • Spring boot 集成 Druid 數(shù)據(jù)源過(guò)程詳解

    Spring boot 集成 Druid 數(shù)據(jù)源過(guò)程詳解

    這篇文章主要介紹了Spring boot 集成 Druid 數(shù)據(jù)源過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-08-08

最新評(píng)論