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 ...
随机推荐
- PHP单引号和双引号对待变量的不同
如果一个变量放在单引号中,会被当作字符串来处理,如果是放在双引号中,则会被当值一个变量来处理(此时可以用 {}扩起来,也可以不用). <?php $txt = "hello, this ...
- Servlet目录
Servlet目录 课时1 Servlet概述12:30 课时2 servlet的第一个例子31:08 课时3 servlet的生命周期18:18 课时4 HttpServlet详细讲解31:43 ...
- MJPhotoBrowser BUG修复
崩溃在loading.progress = (float)receivedSize/expectedSize; 分析:MJPhotoView 执行了hide移除了MJPhotoLoadingView, ...
- js严格模式总结(转~)原文地址http://www.cnblogs.com/chayan/p/5793964.html
首页,我们要理解严格模式的概念,严格模式是一种特殊的执行模式,它修复了部分语言上的不足,提供更强的错误检查,病增强安全性.可以对部分函数进行执行严格模式,如: function func(){ 'us ...
- Android自定义View的实现方法,带你一步步深入了解View(四)
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/17357967 不知不觉中,带你一步步深入了解View系列的文章已经写到第四篇了,回 ...
- Spring控制反转(IOC)和依赖注入(DI),再记不住就去出家!
每次看完spring的东西感觉都理解了,但是过了一段时间就忘,可能是不常用吧,也是没理解好,这次记下来. 拿ssh框架中的action,service,dao这三层举例: 控制反转:完成一个更新用户信 ...
- java 获取本地电脑的分辨率代码
1.代码: java.awt.Toolkit tk=java.awt.Toolkit.getDefaultToolkit(); java.awt.Dimension screenSize= ...
- codeIgniter 文件路径的问题
学习CI的时候,发现一个问题,求指点. 整个项目的头部文件共用,CSS.JS 等文件都一起引入.在以下路径下都没问题. 首页 -- http://localhost/citest/index ...
- Python回调函数用法实例详解
本文实例讲述了Python回调函数用法.分享给大家供大家参考.具体分析如下: 一.百度百科上对回调函数的解释: 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函 ...
- ngixn编译安装时,pcre的处理
nginx编译时pcre会提示找不到libpcre.so.1 ./configure --hlep --without-pcre disable PCRE library usage 不使用pcr ...