Java Thread系列(十)生产者消费者模式

生产者消费者问题(producer-consumer problem),是一个多线程同步问题的经典案例。该问题描述了两个共亨固定大小缓冲区的线程—即所谓的“生产者”和“消费者—在实际运行时会发生的问题。

一、信号灯法

信号灯法实际上就是保证同一时间只有一个线程在操作数据,操作完成后通知其它线程,从而避免死锁。

(1) 生产者

public class Producer implements Runnable {

    private Data data;

    public Producer(Data data) {
this.data = data;
} @Override
public void run() {
for (int i = 0; i < 10; i++) {
data.produce(String.format("product-%s", i));
}
}
}

(2) 消费者

public class Consumer implements Runnable {
private Data data; public Consumer(Data data) {
this.data = data;
} @Override
public void run() {
while (true) {
data.consume();
}
}
}

(3) 数据

public class Data {

    private String data;

    // flag = true  生产者生产,消费者等待,生产完毕后通知消费者消费
// flag = false 消费者消费,生产者等待,消费完毕后通知生产者生产
private boolean flag = true; public synchronized void consume() {
if (flag) {
try {
wait();
} catch (InterruptedException e) {
;
}
} try {
Thread.sleep(1000);
} catch (InterruptedException e) {
;
} notify();
System.out.println("消费者消费:" + getData());
flag = true;
} public synchronized void produce(String data) {
if (!flag) {
try {
wait();
} catch (InterruptedException e) {
;
}
} try {
Thread.sleep(1000);
} catch (InterruptedException e) {
;
} notify();
System.out.println("生产者生产:" + data);
setData(data);
flag = false;
} public String getData() {
return data;
} public void setData(String data) {
this.data = data;
}
}

(4) 测试

public static void main(String[] args) {
Data data = new Data();
new Thread(new Producer(data)).start();
new Thread(new Consumer(data)).start();
}

二、容器法

(1) Producter

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; public class Producter implements Runnable { private BlockingQueue<Data> data;
//用于生成id
private static AtomicInteger count = new AtomicInteger(0); public Producter(BlockingQueue<Data> data) {
this.data = data;
} public Producter() { } @Override
//生产者生产数据
public void run() {
try {
Thread.sleep(2000);
int id = count.incrementAndGet();
if (!this.data.offer(new Data(id, "data-" + id), 2, TimeUnit.SECONDS)) {
System.out.printf("%s生产:data-%s失败\n", Thread.currentThread().getName(), id);
} else {
System.out.printf("%s生产:data-%s\n", Thread.currentThread().getName(), id);
}
} catch (InterruptedException e) {
e.printStackTrace();
} }
}

(2) Consumer

import java.util.concurrent.BlockingQueue;

public class Consumer implements Runnable {

    private BlockingQueue<Data> data;

    public Consumer(BlockingQueue<Data> data) {
this.data = data;
}
public Consumer() { } @Override
//消费者消费数据
public void run() {
Data d = null;
try {
d = this.data.take();
System.out.printf("%s消费:%s\n", Thread.currentThread().getName(), d.getName()); } catch (InterruptedException e) {
e.printStackTrace();
}
}
} public class Data {
private int id;
private String name;
}

(3) 测试

LinkedBlockingQueue<Data> data = new LinkedBlockingQueue<Data>();

Producter p1 = new Producter(data);
Producter p2 = new Producter(data);
Producter p3 = new Producter(data); Consumer c1 = new Consumer(data);
Consumer c2 = new Consumer(data);
Consumer c3 = new Consumer(data); ExecutorService pool = Executors.newCachedThreadPool();
pool.execute(p1);
pool.execute(p2);
pool.execute(p3);
pool.execute(c1);
pool.execute(c2);
pool.execute(c3);
pool.shutdown();

每天用心记录一点点。内容也许不重要,但习惯很重要!

最新文章

  1. 怎么用SAX生成xml文件
  2. 20145206邹京儒《Java程序设计》实验报告一:Java开发环境的熟悉(Windows+IDEA)
  3. PHP PEAR2
  4. Qt调用Server SQL中的存储过程
  5. 简短总结一下C#里跨线程更新UI
  6. ExchangeServeice获取在线outlook邮箱中的未读邮件
  7. Linux学习笔记(2)-用户和用户组
  8. Android 开源控件系列_1
  9. jQuery.validate 中文 API
  10. Next-Key Locks
  11. Android开发----------- 手电筒改进版本号
  12. DeepLearning.ai学习笔记(一)神经网络和深度学习--Week4深层神经网络
  13. js中多维数组转一维
  14. async &amp; await 异步编程的一点巧方法
  15. C#之C#、.NET Framework、CLR的关系
  16. [20181130]如何猜测那些值存在hash冲突.txt
  17. 【leetcode】438. Find All Anagrams in a String
  18. php中正则表达式详解
  19. Eclipse中java内存溢出
  20. linux内核剖析(零)linux系统启动过程详解-开机加电后发生了什么

热门文章

  1. POI2010题解
  2. cocos2dx ui显示机制
  3. How To Enable EPEL Repository in RHEL/CentOS 7/6/5?
  4. 【小技能整理】mac vim开启语法高亮
  5. 使用纯生js实现图片轮换
  6. android studio安装须知
  7. Charles 3断点篡改数据
  8. 1021 docker常用命令和Jenkins搭建
  9. ROS+nfdump 用户上网日志
  10. Oracle DSI系列 01 DSI初识BBED