Java多线程生产者消费者模型实例代码

这篇文章主要介绍“Java多线程生产者消费者模型实例代码”,在日常操作中,相信很多人在Java多线程生产者消费者模型实例代码问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”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_27520480474279Get的值是:1564733938518_27520480474279Set的值是:1564733938518_27520480498378Get的值是:1564733938518_27520480498378Set的值是:1564733938518_27520480540254Get的值是: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的当前值是123Consumer消费了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的当前值是123Consumer消费了value, value的当前值是Producer2生产了value, value的当前值是123Consumer消费了value, value的当前值是Producer2生产了value, value的当前值是123Consumer消费了value, value的当前值是Producer1生产了value, value的当前值是123Consumer消费了value, value的当前值是Producer1生产了value, value的当前值是123Consumer消费了value, value的当前值是Producer1生产了value, value的当前值是123Consumer消费了value, value的当前值是Producer1生产了value, value的当前值是123Consumer消费了value, value的当前值是Producer1生产了value, value的当前值是123Consumer消费了value, value的当前值是······

到此,关于“Java多线程生产者消费者模型实例代码”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!