博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
生产者消费者
阅读量:4072 次
发布时间:2019-05-25

本文共 3945 字,大约阅读时间需要 13 分钟。

生产者和消费者是一种经典的供求案例,生产者和消费者线程之间的关系涉及线程之间的交互。生产者线程产生的数据项,将来会被消费者消费,每个生产出来的数据会被保存在一个共享的仓库中。

假设线程以不同的速度进行,那么将会导致消费者可能获取到还未生产的数据,生产者也有可能在消费者还未取走前一条数据的前提下继续生产,这样就会造成混乱。

为了克服这种混乱,生产者线程必须等待,知道消费者取走之后通知生产者,等待解除,可以生产。如果生产者未生产数据,消费者就要一直等待,直到生产者生产完毕,唤醒消费者线程,取走生产好的数据。

生产者消费者

以下为代码实现:

package my_application;public class ProducerConsumer {
public static void main(String[] args) { ShareStorage s = new ShareStorage(); new Producer(s).start(); new Consumer(s).start(); }}class ShareStorage{
private char c; //此实例变量跟踪两个条件,生产者等待消费者消费一个数据,消费者等待生产者生产一个数据 private volatile boolean flag = true; synchronized void setShareData(char c){ while (!flag) {
//消费者未取走,则生产者等待 try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.c = c; flag = false;//设置标志位为false,告诉消费者可以消费,此时生产者等待 notify(); } synchronized char getShareData(){ while (flag) {
//flag = true ,表示消费者等待,此时生产者生产 try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } flag = true; notify(); return c; }}class Producer extends Thread{
private final ShareStorage shareStorage; Producer(ShareStorage shareStorage){ this.shareStorage = shareStorage; } @Override public void run() { for (char ch = 'A'; ch < 'Z'; ch++) { shareStorage.setShareData(ch); System.out.println(ch + ",生产者生产"); } }}class Consumer extends Thread{
private final ShareStorage shareStorage; Consumer(ShareStorage shareStorage){ this.shareStorage = shareStorage; } @Override public void run() { char ch; do { ch = shareStorage.getShareData(); System.out.println(ch + ",消费者消费"); } while (ch != 'Z'); }}

此时的输出结果可能为:

O,生产者生产O,消费者消费P,生产者生产P,消费者消费

或者

A,生产者生产B,生产者生产A,消费者消费B,消费者消费

这样的输出并不表示消费者和生产者线程没有同步,这是因为setShareData(),getShareData()之后的输出没有被同步造成的结果,为了解决这个问题,加上同步块就可以完美解决这个问题了。见下面修改后的代码:

package my_application;public class ProducerConsumer {
public static void main(String[] args) { ShareStorage s = new ShareStorage(); new Producer(s).start(); new Consumer(s).start(); }}class ShareStorage{
private char c; private volatile boolean flag = true;//写入取走标记 synchronized void setShareData(char c){ while (!flag) {
//消费者未取走,则生产者等待 try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.c = c; flag = false;//设置标志位为false,告诉消费者可以消费,此时生产者等待 notify(); } synchronized char getShareData(){ while (flag) {
//flag = true ,表示消费者等待,此时生产者生产 try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } flag = true; notify(); return c; }}class Producer extends Thread{
private final ShareStorage shareStorage; Producer(ShareStorage shareStorage){ this.shareStorage = shareStorage; } @Override public void run() { for (char ch = 'A'; ch < 'Z'; ch++) { synchronized (shareStorage) { shareStorage.setShareData(ch); System.out.println(ch + ",生产者生产"); } } }}class Consumer extends Thread{
private final ShareStorage shareStorage; Consumer(ShareStorage shareStorage){ this.shareStorage = shareStorage; } @Override public void run() { char ch; do { synchronized (shareStorage) { ch = shareStorage.getShareData(); System.out.println(ch + ",消费者消费"); } } while (ch != 'Z'); }}

输出结果:

A,生产者生产A,消费者消费B,生产者生产B,消费者消费C,生产者生产C,消费者消费D,生产者生产D,消费者消费E,生产者生产E,消费者消费...

转载地址:http://pdrji.baihongyu.com/

你可能感兴趣的文章
React Native(四):布局(使用Flexbox)
查看>>
React Native(七):Android双击Back键退出应用
查看>>
Android自定义apk名称、版本号自增
查看>>
adb command not found
查看>>
Xcode 启动页面禁用和显示
查看>>
【剑指offer】q50:树中结点的最近祖先
查看>>
二叉树的非递归遍历
查看>>
【leetcode】Reorder List (python)
查看>>
【leetcode】Linked List Cycle (python)
查看>>
【leetcode】Candy(python)
查看>>
【leetcode】Sum Root to leaf Numbers
查看>>
【leetcode】Pascal's Triangle II (python)
查看>>
java自定义容器排序的两种方法
查看>>
如何成为编程高手
查看>>
本科生的编程水平到底有多高
查看>>
备忘:java中的递归
查看>>
Solr及Spring-Data-Solr入门学习
查看>>
python_time模块
查看>>
python_configparser(解析ini)
查看>>
selenium学习资料
查看>>