每次都是隔很长时间才在博客中写点什么,说自己忙吧,这是给自己的一个借口,其实呢还是懒啊。哎。。。

最近项目中有个对比的需求,需要从日志文件中获取到参数,然后调用不同的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的使用的更多相关文章

  1. Java BlockingQueue Example(如何使用阻塞队列实现生产者-消费者问题)

    Today we will look into Java BlockingQueue. java.util.concurrent.BlockingQueue is a java Queue that ...

  2. Java BlockingQueue是什么?

    Java BlockingQueue是一个并发集合util包的一部分.BlockingQueue队列是一种支持操作,它等待元素变得可用时来检索,同样等待空间可用时来存储元素.

  3. [JAVA] BlockingQueue学习

    有点时间,巩固巩固下基础知识:BlockingQueue,如果BlockQueue是空的,从BlockingQueue取东西的操作将会被阻断进入等待状态,直到BlockingQueue进了东西才会被唤 ...

  4. 建房子之前先挖地基 - Java BlockingQueue理解

    最近一直在看<Think In Java>里关于并发部分的章节,读到第二十一章有一个有趣的比喻:必须先挖房子的地基,但是接下来可以并行的铺设钢结构和构建水泥部件,而这两项任务必须在混凝土浇 ...

  5. java BlockingQueue 用法

    在新增的Concurrent包中,BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题.通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利.本文 ...

  6. Go 中的 channel 与 Java BlockingQueue 的本质区别

    前言 最近在实现两个需求,由于两者之间并没有依赖关系,所以想利用队列进行解耦:但在 Go 的标准库中并没有现成可用并且并发安全的数据结构:但 Go 提供了一个更加优雅的解决方案,那就是 channel ...

  7. Java - BlockingQueue

    https://juejin.im/post/5aeebd02518825672f19c546 https://www.infoq.cn/article/java-blocking-queue blo ...

  8. java并发编程工具类JUC第一篇:BlockingQueue阻塞队列

    Java BlockingQueue接口java.util.concurrent.BlockingQueue表示一个可以存取元素,并且线程安全的队列.换句话说,当多线程同时从 JavaBlocking ...

  9. 10个经典的Java面试题

    这里有10个经典的Java面试题,也为大家列出了答案.这是Java开发人员面试经常容易遇到的问题,相信你了解和掌握之后一定会有所提高.让我们一起来看看吧. 1.Java的HashMap是如何工作的? ...

  10. 10个经典的Java面试题集合(转载)

    1.Java的HashMap是如何工作的? HashMap是一个针对数据结构的键值,每个键都会有相应的值,关键是识别这样的值. HashMap 基于 hashing 原理,我们通过 put ()和 g ...

随机推荐

  1. zabbix nagios 类nagios 之 不以性能为前提的开发和监控都是瞎扯淡

    从最初的nagios到现在强大的zabbix 3.0,我想说,不以性能为前提的开发和监控都是瞎扯淡? 首先我对这两款监控软件的认识: zabbix,很多企业都在用,给人的感觉是很炫,不过我个人觉得虽然 ...

  2. 有1,2,3一直到n的无序数组,排序

    题目:有1,2,3,..n 的无序整数数组,求排序算法.要求时间复杂度 O(n), 空间复杂度O(1). 分析:对于一般数组的排序显然 O(n) 是无法完成的. 既然题目这样要求,肯定原先的数组有一定 ...

  3. Spring @RequestParam @RequestBody @PathVariable 等参数绑定注解详解

    背景 昨天一个人瞎倒腾spring boot,然后遇到了一点问题,所以把这个问题总结一下. 主要讲解request 数据到handler method 参数数据的绑定,所用到的注解和什么情形下使用. ...

  4. postgreSQL 统计语句

    pg_stat_statements 是 postgresql 的一个扩展,用来统计查询语句,类似于 mysql 的 慢查询. 安装二进制文件 有些发行版可能没有附带这个扩展,则需要用户自己安装, 本 ...

  5. windows获取硬盘使用率等信息

    #coding=utf8 import psutil cpu = {'user' : 0, 'system' : 0, 'idle' : 0, 'percent' : 0} mem = {'total ...

  6. 性能:CPU、Memory、耗电量

    1.自动 APP 性能测试需求讨论:https://testerhome.com/topics/3172 2.Android Studio中怎么使用DDMS工具?:http://www.cnblogs ...

  7. vim c++补全

    弄了个vim对c++的补全,主要参考自: http://vim.wikia.com/wiki/C%2B%2B_code_completion   首先确定vim编辑.cc或者.cpp文件时当前自动补全 ...

  8. Spring 容器

    Spring提供了两个核心接口:BeanFactory和ApplicationContext,其中applicationContext是BeanFactory的子接口. 他们都可代表Spring容器, ...

  9. Android studio 分析内存泄漏

    以前用eclipse的时候,我们采用的是DDMS和MAT,不仅使用步骤复杂繁琐,而且要手动排查内存泄漏的位置,操作起来比较麻烦.后来随着Android studio的潮流,我也抛弃了eclipse加入 ...

  10. knapsack problem 背包问题 贪婪算法GA

    knapsack problem 背包问题贪婪算法GA 给点n个物品,第j个物品的重量,价值,背包的容量为.应选哪些物品放入包内使物品总价值最大? 规划模型 max s.t. 贪婪算法(GA) 1.按 ...