中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java多線程中生產者消費者模型的示例分析

發布時間:2021-07-15 13:43:39 來源:億速云 閱讀:111 作者:小新 欄目:編程語言

小編給大家分享一下Java多線程中生產者消費者模型的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

生產者消費者模型

生產者:生產任務的個體;

消費者:消費任務的個體;

緩沖區:是生產者和消費者之間的媒介,對生產者和消費者解耦。


緩沖區元素為滿,生產者無法生產,消費者繼續消費;

緩沖區元素為空,消費者無法消費,生產者繼續生產;

wait()/notify()生產者消費者模型

制作一個簡單的緩沖區ValueObject,value為空表示緩沖區為空,value不為空表示緩沖區滿

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

生產者,緩沖區滿則wait(),不再生產,等待消費者notify(),緩沖區為空則開始生產

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

消費者,緩沖區為空則wait(),等待生產者notify(),緩沖區為滿,消費者開始消費

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方法,啟動一個生產者和一個消費者

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

運行結果如下

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

生產者和消費者交替運行,生產者生產一個字符串,緩沖區為滿,消費者消費一個字符串,緩沖區為空,循環往復,滿足生產者/消費者模型。

await()/signal()生產者/消費者模型

緩沖區

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

ThreadDomain48繼承ReentrantLock,set方法生產,get方法消費

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() + "生產了value, value的當前值是" + 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() + "消費了value, value的當前值是" + ValueObject.value);
      condition.signal();
    }
    catch (InterruptedException e)
    {
      e.printStackTrace();
    }
    finally
    {
      unlock();
    }
  }
}

MyThread41啟動兩個生產線程和一個消費線程

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

輸出結果如下

Producer1生產了value, value的當前值是123
Consumer消費了value, value的當前值是
Producer1生產了value, value的當前值是123

為什么Producer2無法生產,消費者無法消費呢?是因為此時緩沖區為滿,Producer1的notify()應該喚醒Consumer卻喚醒了Producer2,導致Producer2因為緩沖區為滿和Consumer沒有被喚醒而處于waiting狀態,此時三個線程均在等待,出現了假死。

解決方案有兩種:

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

2.使用兩個Condition,生產者Condition和消費者Condition,喚醒指定的線程;

正常輸入如下:

······
Producer2生產了value, value的當前值是123
Consumer消費了value, value的當前值是
Producer2生產了value, value的當前值是123
Consumer消費了value, value的當前值是
Producer2生產了value, value的當前值是123
Consumer消費了value, value的當前值是
Producer1生產了value, value的當前值是123
Consumer消費了value, value的當前值是
Producer1生產了value, value的當前值是123
Consumer消費了value, value的當前值是
Producer1生產了value, value的當前值是123
Consumer消費了value, value的當前值是
Producer1生產了value, value的當前值是123
Consumer消費了value, value的當前值是
Producer1生產了value, value的當前值是123
Consumer消費了value, value的當前值是
······

以上是“Java多線程中生產者消費者模型的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

玉屏| 杭锦旗| 红河县| 渑池县| 四子王旗| 兴城市| 东城区| 吉木萨尔县| 吕梁市| 若尔盖县| 舞阳县| 宜兰县| 华蓥市| 同江市| 华池县| 蒙城县| 清水县| 崇义县| 南平市| 浦县| 绵阳市| 寿阳县| 日照市| 德安县| 鄱阳县| 大安市| 兴宁市| 枞阳县| 丰原市| 扶风县| 柘城县| 安泽县| 曲阳县| 连州市| 仙桃市| 崇礼县| 陆川县| 东明县| 虎林市| 台北县| 井研县|