Java-BlockingQueue的使用
每次都是隔很长时间才在博客中写点什么,说自己忙吧,这是给自己的一个借口,其实呢还是懒啊。哎。。。
最近项目中有个对比的需求,需要从日志文件中获取到参数,然后调用不同的API,进行结果的对比。但是不知用什么方式比较好,于是查了下jdk的手册,发现了BlockingQueue这个好东西。
关于BlockingQueue的介绍,大家有兴趣的可以自己看下:http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/LinkedBlockingQueue.html
需求呢其实很简单就是将参数放置到Queue中,然后交由下一个策略去消费。刚开始时是通过不同的线程往队列中存放数据,然后返回给下个服务一个BlockingQueue的对象,下一个策略从队列中消费,code如下:
@SuppressWarnings("rawtypes")
@Override
public BlockingQueue getTxtLogContent(String path) {
File file = new File(path);
BufferedReader reader = null;
String tempStr = null;
final BlockingQueue queue = new LinkedBlockingQueue();
try {
reader = new BufferedReader(new FileReader(file));
while ((tempStr = reader.readLine()) != null) {
final InputOutputPrameters parameter = new InputOutputPrameters();
String[] list = tempStr.split(";");
if (list != null && list.length > 0) {
parameter.setInputParamters(list[0]);
parameter.setOutputParameters(list[1]);
}
new Thread(){
@SuppressWarnings("unchecked")
public void run(){
try {
Thread.sleep((long)(Math.random()*100));
log.info("开始存入数据!");
queue.put(parameter);
log.info("已经存入数据,目前队列中有 " + queue.size() +" 个队列!输入参数:"+ parameter.getInputParamters() + ";\n输出参数:" + parameter.getOutputParameters());
} catch (Exception e) {
log.error("系统异常:" + e);
}
}
}.start();
}
reader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (reader != null) {
try {
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
return queue;
}
可是在实际运行时,由于日志比较大,下一个策略可能要等1hour或更长的时间才能开始处理,这明显是不符合要求的,于是又优化了下,将BlockingQueue改为全局static的,然后下一个策略可以直接监控这个队列中是否有值,有值就消费,没值就阻塞线程等待或者超时等其他处理。
改进后的code:
1、新建一个队列类:
public class ParameterQueue extends LinkedBlockingQueue<InputOutputPrameters> { /**
*@Fields serialVersionUID:
*/
private static final long serialVersionUID = 6032356446145302484L; private static BlockingQueue<InputOutputPrameters> queue = new LinkedBlockingQueue<InputOutputPrameters>(); /**
* @Fields log: 日志记录
*/
private static final Logger log = LoggerFactory
.getLogger(ParameterQueue.class); /**
* 获取队列中的对象
* @Method:getParameter
* @Description: 获取队列中的对象
* @return 获取到的对象信息
*/
public static InputOutputPrameters getParameter(){
InputOutputPrameters result = null;
try {
result = (InputOutputPrameters)queue.take();
} catch (Exception e) {
log.error("获取队列异常,异常信息:" + e);
}
return result;
} /**
* 获取队列的数量
* @Method:getQueueSize
* @Description: 获取队列的数量
* @return 数量
*/
public static Integer getQueueSize() {
return queue.size();
} /**
* 放置参数到队列中
* @Method:putParameter
* @Description: 放置参数到队列中
* @param parameter 要放置的对象
*/
public static void putParameter(InputOutputPrameters parameter) {
try {
queue.put(parameter);
} catch (Exception e) {
log.error("插入队列异常,异常信息:" + e);
}
}
}
2、读取文件时,直接操作该队列,往队列中put值,下一个策略从该队列中get值,put的code如下:
public void getSource(String path) {
try {
File file = new File(path);
BufferedReader reader = null;
String tempStr = null;
try {
reader = new BufferedReader(new FileReader(file));
while ((tempStr = reader.readLine()) != null) {
final InputOutputPrameters parameter = new InputOutputPrameters();
String[] list = tempStr.split(";");
if (list != null && list.length > 0) {
parameter.setInputParamters(list[0]);
parameter.setOutputParameters(list[1]);
}
putInQueue(parameter);
}
reader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (reader != null) {
try {
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
} catch (Exception e) {
log.error("系统异常: " + e);
}
} /**
* 将参数存放至队列中
* @Method:putInQueue
* @Description: 将参数存放至队列中
* @param parameter 要存放的对象
*/
private void putInQueue(final InputOutputPrameters parameter) {
new Thread(){
public void run(){
try {
Thread.sleep((long)(Math.random()*100));
log.info("开始存入数据!");
ParameterQueue.putParameter(parameter);
log.info("已经存入数据,目前队列中有 " + ParameterQueue.getQueueSize() +" 个队列!输入参数:"+ parameter.getInputParamters() + ";\n输出参数:" + parameter.getOutputParameters());
} catch (Exception e) {
log.error("系统异常:" + e);
}
}
}.start();
}
于是这个要求就达到了。记录下这个小需求,方便以后查阅。
简要说下,BlockingQueue是线程安全的,常用的是ArrayBlockingQueue、LinkedBlockingQueue
ArrayBlockingQueue需要制定容量,而LinkedBlockingQueue不需要
同时在消费时,take()是会阻塞线程的,如果是单线程跑时,take()不到时整个线程就卡了
所以看具体环境需求,是用take还是其他的,我一般用poll,因为可以制定超时时间。
哎 不知道怎么写了,就这样吧。
Java-BlockingQueue的使用的更多相关文章
- Java BlockingQueue Example(如何使用阻塞队列实现生产者-消费者问题)
Today we will look into Java BlockingQueue. java.util.concurrent.BlockingQueue is a java Queue that ...
- Java BlockingQueue是什么?
Java BlockingQueue是一个并发集合util包的一部分.BlockingQueue队列是一种支持操作,它等待元素变得可用时来检索,同样等待空间可用时来存储元素.
- [JAVA] BlockingQueue学习
有点时间,巩固巩固下基础知识:BlockingQueue,如果BlockQueue是空的,从BlockingQueue取东西的操作将会被阻断进入等待状态,直到BlockingQueue进了东西才会被唤 ...
- 建房子之前先挖地基 - Java BlockingQueue理解
最近一直在看<Think In Java>里关于并发部分的章节,读到第二十一章有一个有趣的比喻:必须先挖房子的地基,但是接下来可以并行的铺设钢结构和构建水泥部件,而这两项任务必须在混凝土浇 ...
- java BlockingQueue 用法
在新增的Concurrent包中,BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题.通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利.本文 ...
- Go 中的 channel 与 Java BlockingQueue 的本质区别
前言 最近在实现两个需求,由于两者之间并没有依赖关系,所以想利用队列进行解耦:但在 Go 的标准库中并没有现成可用并且并发安全的数据结构:但 Go 提供了一个更加优雅的解决方案,那就是 channel ...
- Java - BlockingQueue
https://juejin.im/post/5aeebd02518825672f19c546 https://www.infoq.cn/article/java-blocking-queue blo ...
- java并发编程工具类JUC第一篇:BlockingQueue阻塞队列
Java BlockingQueue接口java.util.concurrent.BlockingQueue表示一个可以存取元素,并且线程安全的队列.换句话说,当多线程同时从 JavaBlocking ...
- 10个经典的Java面试题
这里有10个经典的Java面试题,也为大家列出了答案.这是Java开发人员面试经常容易遇到的问题,相信你了解和掌握之后一定会有所提高.让我们一起来看看吧. 1.Java的HashMap是如何工作的? ...
- 10个经典的Java面试题集合(转载)
1.Java的HashMap是如何工作的? HashMap是一个针对数据结构的键值,每个键都会有相应的值,关键是识别这样的值. HashMap 基于 hashing 原理,我们通过 put ()和 g ...
随机推荐
- Python 9X9乘法口诀表
#乘法口诀 for i in range(1,10): for j in range(1,i+1): print ( j,'*',i,'=',j*i,'',' ',end='') print(end= ...
- 用keras的cnn做人脸分类
keras介绍 Keras是一个简约,高度模块化的神经网络库.采用Python / Theano开发. 使用Keras如果你需要一个深度学习库: 可以很容易和快速实现原型(通过总模块化,极简主义,和可 ...
- C# 5.0新推出的async和await
class Program { static void Main(string[] args) { Test t = new Test(); } } public class Test { publi ...
- NDB Cluster 存储引擎物理备份
NDB Cluster 存储引擎物理备份NDB Cluster 存储引擎也是一款事务性存储引擎,和Innodb 一样也有redo 日志.NDBCluter 存储引擎自己提供了备份功能,可以通过相关的命 ...
- [修改后]html+css 做成一个可浏览的表格
现在表格内容需要显示的要求如下: 1, 表格很大,界面放不小,需要放到div中. 2, 在div中可以用scroll滑动查看. 3, td中的内容保持在一行中. 4, 可以点击tr,然后可以选中并了解 ...
- ASP.NET MVC分页组件MvcPager 2.0版发布暨网站全新改版
MvcPager分页控件是在ASP.NET MVC Web应用程序中实现分页功能的一系列扩展方法,该分页控件的最初的实现方法借鉴了网上流行的部分源代码, 尤其是ScottGu的PagedList< ...
- yii 图片展示
<?= DetailView::widget([ 'model' => $model, 'attributes' => [ 'id', 'name', 'time', 'pic', ...
- sql server 远程连接不上解决思路
1.数据库是否允许远程连接: 1.1.0登陆SQL Server 2008(windows身份认证),登陆后右击,选择“属性”.左侧选择“安全性”,选中右侧的“SQL Server 和 Windows ...
- js性能优化
使用局部变量(尽量缩短作用域链)JavaScript引擎对变量的解析时间跟作用域链的深度有关.局部变量由于处于链尾,存取速度是最快的,因此,一个好的经验是:任何非局部变量使用超过一次时,请使用局部变量 ...
- c++:string函数
string类的构造函数:string(const char *s); //用c字符串s初始化string(int n,char c); //用n个字符c初始化此外,string类还支持 ...