多生产者多消费者(第二种方式2.1)基于BlockingQueue
public class Producer implements Runnable {
//静态变量只初始化一次
private static AtomicInteger count = new AtomicInteger();
private volatile boolean isRunning = true;
private BlockingQueue<String> queue;
private String name;
public Producer(BlockingQueue<String> queue, String name) {
this.queue = queue;
this.name = name;
}
public void run() {
String data = null;
Random r = new Random();
System.out.println("启动" + name);
try {
while (isRunning) {
Thread.sleep(r.nextInt());
data = "data:" + count.incrementAndGet();
System.out.println(name + "生产数据:" + data);
queue.put(data);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name + "退出!");
}
public void stop() {
isRunning = false;
}
}
public class Consumer implements Runnable {
private volatile boolean isRunning = true;
private BlockingQueue<String> queue;
private String name;
public Consumer(BlockingQueue<String> queue, String name) {
this.queue = queue;
this.name = name;
}
public void run() {
System.out.println("启动" + name);
try {
while (isRunning) {
String data = queue.take();
System.out.println(name + "消费数据:" + data);
Thread.sleep();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name + "退出!");
}
public void stop() {
isRunning = false;
}
}
public class Client {
public static void main(String[] args) throws InterruptedException {
// 声明一个容量为10的缓存队列
BlockingQueue<String> queue = new LinkedBlockingQueue<String>();
Producer producer1 = new Producer(queue , "【生产者一】");
Producer producer2 = new Producer(queue ,"【生产者二】");
Consumer consumer1 = new Consumer(queue ,"【消费者一】");
// 借助Executors
ExecutorService service = Executors.newCachedThreadPool();
// 启动线程
service.execute(producer1);
service.execute(producer2);
service.execute(consumer1);
// 执行7s
Thread.sleep( * );
producer1.stop();
producer2.stop();
service.shutdown();
}
}
队列的操作:
offer 是向队列尾部添加元素,返回true或者false
poll 是从队列头部取数据,如果没有取到返回null
offer和poll都不会阻塞当前线程
阻塞操作
put 往队列当中中放入数据
take 从队列当中取数据
多生产者多消费者(第二种方式2.1)基于BlockingQueue的更多相关文章
- Java创建线程的第二种方式:实现runable接口
/*需求:简单的卖票程序多个窗口买票 创建线程的第二种方式:实现runable接口 *//*步骤1.定义类实现Runable接口2.覆盖Runable接口中的run方法 将线程要运行的代码存放在 ...
- JS定义函数的2种方式以及区别简述(为什么推荐第二种方式)
无意中看到了阮一峰大神多年前的一篇博客: 12种不宜使用的Javascript语法 看到第9条的时候受到了启发,感觉之前没怎么理解清楚的一些问题好像突然就清晰了,如下图 可能光这样看,有些小伙 ...
- Spring整合Struts2框架的第二种方式(Action由Spring框架来创建)(推荐大家来使用的)
1. spring整合struts的基本操作见我的博文:https://www.cnblogs.com/wyhluckdog/p/10140588.html,这里面将spring与struts2框架整 ...
- 创建线程的第二种方式------实现Runnable接口的方式
package cn.itcast.demo16.Demo07.Runnable;/** * @author newcityman * @date 2019/7/22 - 23:17 */public ...
- 多线程-创建线程第二种方式-实现Runnable接口-细节和好处
1 package multithread2; 2 3 /* 4 * 创建线程的第一种方法:继承Thread类 5 * 6 * 创建线程的第二种方式:实现Runnable接口 7 * 8 * 1,定义 ...
- Thread类的常用方法_sleep和创建多线程程序的第二种方式_实现Runnable接口
sleep方法是在Thread类中的一个静态方法,当一个线程调用了sleep方法,被调用的那个线程就会暂时的让出指定时间的CPU执行权,在这段时间也不会参与CPU的调度,当时间到了之后,就会重新回到就 ...
- throws关键字_异常处理的第一种方式(交给别人处理)和try_catch_异常处理的第二种方式(自己处理)
throws关键字:异常处理的第一种方式,交给别人处理 作用: 当方法内部抛出异常对象的时候,那么我们就必须处理这个异常对象 可以使用throws关键字处理异常对象, 会把异常对象声明抛出给方法的调用 ...
- 第二种方式读取并显示HDFS中的内容
1.讀取HDFS内容的java客戶端代碼: package Hdfs; import java.io.InputStream; import java.net.URI; import org.apac ...
- Struts2框架的数据封装一之属性封装(属性封装的第二种方式:封装成javaBean)
Struts2中提供了两类数据封装的方式? 第一种方式:属性驱动(有两种方式:一个对属性,另外一个是将参数封装到javaBean中) B. 在页面上,使用OGNL表达式进行数据封装.(将参数封装到ja ...
- SpringMVC实现操作的第二种方式
一: 运行效果: 点击提交之后显示效果 二: (1).web.xml <?xml version="1.0" encoding="UTF-8"?> ...
随机推荐
- LightOJ - 1333 - Grid Coloring
链接: https://vjudge.net/problem/LightOJ-1333 题意: You have to color an M x N two dimensional grid. You ...
- .net core 根据已有数据库创建实体Model
这三个引用需要与.net core 版本一致,否则后续其他操作时会出错 可以到NuGET包中找到对应的版本然后添加,或者使用一下语句将版本号修改为.net core对应的版本然后执行 Install- ...
- HTML音乐标签和滚动
<!-- 音乐标签 --> <embed src="1.mp3" type=""> <embed src="1.mp3& ...
- Educational Codeforces Round 67
Educational Codeforces Round 67 CF1187B Letters Shop 二分 https://codeforces.com/contest/1187/submissi ...
- 【luoguP5091】【模板】欧拉定理
题目链接 欧拉定理: 当\(a\),\(m\)互质时,\(a^{\phi(m)}\equiv 1 (mod ~ m)\) 扩展欧拉定理: 当\(B>\phi(m)\)时,\(a^B\equiv ...
- kafka-python 1.4.6 版本触发的一个 rebalance 问题
在使用了最新版的 kafka-python 1.4.6 在 broker 对 topic 进行默认配置的情况下报出类似错误 CommitFailedError CommitFailedError: C ...
- C++ 类型转换符区别分析
转载自:https://blog.csdn.net/legalhighhigh/article/details/87459995 1.static_cast用于将参数转换为指定类型.需要注意的是,进行 ...
- 理解Web路由(浅谈前后端路由与前后端渲染)
1.什么是路由? 在Web开发过程中,经常会遇到『路由』的概念.那么,到底什么是路由?简单来说,路由就是URL到函数的映射. 路由的概念最开始是由后端提出来的,在以前用模板引擎开发页面的时候,是使用路 ...
- 统一异常处理@ControllerAdvice
一.异常处理 有异常就必须处理,通常会在方法后面throws异常,或者是在方法内部进行try catch处理. 直接throws Exception 直接throws Exception,抛的异常太过 ...
- Net core学习系列(三)——Net Core中的依赖注入
本文通过一个维修工与工具库的例子形象的描述一下为什么要用依赖注入.它的工作原理是什么样的, 然后根据这个类比一下ASP.NET Core 中的依赖注入, 从而深刻了解它的使用方法.注意事项以及回收机制 ...