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

发布时间:2021-08-17 18:38:51 作者:chen
来源:亿速云 阅读:109

这篇文章主要介绍“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多线程生产者消费者模型实例代码”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

推荐阅读:
  1. 基于POSIX的信号量的生产者消费者模型
  2. python之生产者消费者模型实现详解

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:java怎么读取cvs文件并导入数据库

下一篇:Java怎么用阻塞队列控制线程通信

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》