最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

生產(chǎn)者:生產(chǎn)任務的個體;

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

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


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

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

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

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

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

生產(chǎn)者,緩沖區(qū)滿則wait(),不再生產(chǎn),等待消費者notify(),緩沖區(qū)為空則開始生產(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();
    }
  }
}

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

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

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
······

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

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

緩沖區(qū)

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

ThreadDomain48繼承ReentrantLock,set方法生產(chǎn),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() + "生產(chǎn)了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啟動兩個生產(chǎn)線程和一個消費線程

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生產(chǎn)了value, value的當前值是123
Consumer消費了value, value的當前值是
Producer1生產(chǎn)了value, value的當前值是123

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

解決方案有兩種:

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

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

正常輸入如下:

······
Producer2生產(chǎn)了value, value的當前值是123
Consumer消費了value, value的當前值是
Producer2生產(chǎn)了value, value的當前值是123
Consumer消費了value, value的當前值是
Producer2生產(chǎn)了value, value的當前值是123
Consumer消費了value, value的當前值是
Producer1生產(chǎn)了value, value的當前值是123
Consumer消費了value, value的當前值是
Producer1生產(chǎn)了value, value的當前值是123
Consumer消費了value, value的當前值是
Producer1生產(chǎn)了value, value的當前值是123
Consumer消費了value, value的當前值是
Producer1生產(chǎn)了value, value的當前值是123
Consumer消費了value, value的當前值是
Producer1生產(chǎn)了value, value的當前值是123
Consumer消費了value, value的當前值是
······

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

最新評論

东港市| 夹江县| 呼伦贝尔市| 晋宁县| 延川县| 万山特区| 子洲县| 浪卡子县| 册亨县| 辽阳市| 利辛县| 西吉县| 辽宁省| 崇州市| 尼玛县| 静海县| 河津市| 上栗县| 天峨县| 且末县| 双鸭山市| 惠州市| 旅游| 辽阳市| 承德市| 分宜县| 宁陵县| 永新县| 揭西县| 连云港市| 大邑县| 上杭县| 都昌县| 乌拉特中旗| 长丰县| 西乌珠穆沁旗| 瓦房店市| 自治县| 泰安市| 正蓝旗| 荥经县|