Java并发包——Blockingqueue,ConcurrentLinkedQueue,Executors
背景
通过做以下一个小的接口系统gate,了解一下mina和java并发包里的东西。A系统为javaweb项目,B为C语言项目,gate是本篇须要完毕的系统。
需求
1. A为集群系统,并发较高,会批量发送给gate消息,而且接受gate返回的消息。
2. gate独立部署,将从A接受到的消息压入队列,与B建立连接后,将每条消息验证签名等工作后,发送给B。须要保证性能;
3. B负责处理消息,并返回处理结果,B为gate提供提供六个port,一个port可有三个长连接(须由gate发送心跳保持长连接,否则超时切断连接)。
实例
项目中用到了两个框架mina2.0.7和axis2。首先,gate须要接收从A发送过来的消息。为保证消息顺序性。压入队列中。为保证性能。将队列中的消息通过不同的连接发送至B,这让我们非常快就想到了多线程中生产者消费者的那张图,而且这是一个生产者。多个消费者,以下我们来看代码。
首先,gate作为服务端,要为A提供一个接口,使用axis2完毕了。关于webservice就不必多说,可看我前面的博客。配置例如以下:
<serviceGroup>
<service name="sendService" scope="application">
<description>
SendService
</description>
<messageReceivers>
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only" class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out" class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
</messageReceivers>
<parameter name="ServiceClass">
cn.net.easyway.customer.SendService
</parameter>
</service>
</serviceGroup>
以下是服务实现类:
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import cn.net.easyway.nds.MsgConsumer;
import cn.net.easyway.nds.MsgProducer; /**
* 为用户管理系统提供服务接口
* @author yuanfubiao
*
*/
public class SendService { private static Log logger = LogFactory.getLog(SendService.class); private static int num = 0;
//消息队列
private static LinkedBlockingQueue<String> msgQueue = new LinkedBlockingQueue<String>();
//生产者线程池
private static ExecutorService executorProducer = Executors.newFixedThreadPool(20); //创建20个线程。应对并发较高的情况
//消费者线程池
private static ExecutorService executorCustomer = Executors.newFixedThreadPool(18); //和连接数相应 /**
* 放入消息
* @param list 消息列表
*/
public void putMsg(List<String> list){ //将消息放入队列
executorProducer.execute(new MsgProducer(msgQueue,list)); //取出消息:数据量大,启用全部线程
if(list.size() > 18){
for(int i=0;i<18;i++){
executorCustomer.execute(new MsgConsumer(msgQueue));
}
}else{
executorCustomer.execute(new MsgConsumer(msgQueue));
}
}
}
Java并发包为我们提供了非常多有用的多线程东西,因此没有必要自己去实现一个队列和线程池。如上面代码我们用到的队列是LinkedBlockingQueue,他为线程安全的堵塞队列。多线程操作时不必为了同步而担心。而且会将进出两边自己主动负载,他实现自BlockingQueue接口。
从jdk中能够看到实现BlockingQueue接口的还有ArrayBlockingQueue,DelayQueue,
LinkedBlockingDeque,LinkedBlockingQueue,LinkedTransferQueue,PriorityBlockingQueue,SynchronousQueue;此接口就是提供一个堵塞队列,从api中我们看到例如以下一张图:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvU3R1YmJvcm5Qb3RhdG9lcw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
Throwsexception:当队列已满。再次加入会抛出错误,取数据也是如此。
Specialvalue:加入或取出时会有一个返回值;
Blocks:是在队列已满或为空时,会一直堵塞;
Time Out:指堵塞到一定时间。线程退出。
当中,另一个并发队列也是作为生产者消费者的首选:ConcurrentLinkedQueue,它是非堵塞队列。肯定就不是出自Blockingqueue接口,而是出自AbstractQueue,因此也就没有put和take方法,使用这个并发队列须要有两点注意:第一。推断是否为空尽量使用isEmpty方法。不要用size()。有人測试过size方法非常耗费时间。第二就是线程问题。尽管ConcurrentLinkedQueue是线程安全的,可是仅仅负责原子性的。就是说当你操作queue.add()
or queue.poll的时候是安全的。当并发量较大时,你在使用queue.isEmpty时还不为空,但就在这空当有可能就运行poll操作。导致队列为空引起异常,可用例如以下代码:
synchronized(queue) {
if(!queue.isEmpty()) {
queue.poll();
}
}
在gate中。我定义了两个线程池。一个是生产者。还有一个是消费者:
//生产者线程池
private static ExecutorService executorProducer = Executors.newFixedThreadPool(20); //创建20个线程。应对并发较高的情况
//消费者线程池
private static ExecutorService executorCustomer = Executors.newFixedThreadPool(18);
Executors提供了一个工厂方法,用来创建线程池。返回的线程池都实现了ExecutorService接口,能够创建例如以下线程池:
newCachedThreadPool():创建一个可缓存的线程池,调用execute将重用曾经构造的线程。假设如今线程没有可用的,则创建一个新线程加入到池中,终止并从缓存中溢出那些已有60秒未被使用的线程;
newFixedThreadPool(intnThreads):创建固定的线程;
newScheduledThreadPool(intcorePoolSize):创建一个支持定时及周期性的任务运行的线程池;
newSingleThreadExecutor():创建一个单线程的Executor。
启动线程。有两个方法。一个是execute(),还有一个是submit(),后者是有返回值的,会将运行的结果Future返回,关于Future可移步这里。
以下就是生产者和消费者代码:
生产者:
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue; /**
* 向队列加入消息
* @author yuanfubiao
*
*/
public class MsgProducer implements Runnable { private LinkedBlockingQueue<String> msgQueue; private List<String> message; public MsgProducer(LinkedBlockingQueue<String> queue,List<String> msg) {
this.msgQueue = queue;
this.message = msg;
} @Override
public void run() {
Iterator<String> iter = message.iterator();
while(iter.hasNext()){
String msg = iter.next();
try {
msgQueue.put(msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
消费者:
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.LinkedBlockingQueue; import nds.framework.security.NDSMD5; import org.apache.commons.codec.binary.Hex;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.mina.core.session.IoSession; /**
* 从消息队列取出消息
* @author yuanfubiao
*
*/
public class MsgConsumer implements Runnable{ private static Log logger = LogFactory.getLog(MsgConsumer.class);
private LinkedBlockingQueue<String> msgQueue; public MsgConsumer(LinkedBlockingQueue<String> queue) {
this.msgQueue = queue;
} @Override
public void run() {
while(!msgQueue.isEmpty()){ String msg = null;
try {
msg = msgQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
} if(null == msg){
return;
} //增加时间
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
String now = format.format(new Date());
String prefix = msg.substring(0, 19);
String suffix = msg.substring(33, msg.length());
String packet = prefix.trim() + now.trim() + suffix.trim(); //签名部分忽略
//TODO
String newStr = packet // 签名 + signature.toUpperCase().trim();
//关于mina,可见我下篇文章
IoSession session = SessionPool.getSession(newStr.substring(13, 15));
logger.info("发送数据:" + newStr);
session.write(newStr); try {
Thread.sleep(1000); //等待一秒
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
}
源代码下载:http://download.csdn.net/detail/stubbornpotatoes/7438435
Java并发包——Blockingqueue,ConcurrentLinkedQueue,Executors的更多相关文章
- Java并发包线程池之Executors、ExecutorCompletionService工具类
前言 前面介绍了Java并发包提供的三种线程池,它们用处各不相同,接下来介绍一些工具类,对这三种线程池的使用. Executors Executors是JDK1.5就开始存在是一个线程池工具类,它定义 ...
- Java并发包源码学习系列:基于CAS非阻塞并发队列ConcurrentLinkedQueue源码解析
目录 非阻塞并发队列ConcurrentLinkedQueue概述 结构组成 基本不变式 head的不变式与可变式 tail的不变式与可变式 offer操作 源码解析 图解offer操作 JDK1.6 ...
- Java并发包分析——BlockingQueue
之前因为找实习的缘故,博客1个多月没有写了.找实习的经历总算告一段落,现在重新更新博客,这次的内容是分析Java并发包中的阻塞队列 关于阻塞队列,我之前是一直充满好奇,很好奇这个阻塞是怎么实现.现在我 ...
- Java并发包探秘 (一) ConcurrentLinkedQueue
本文是Java并发包探秘的第一篇,旨在介绍一下Java并发容器中用的一些思路和技巧,帮助大家更好的理解Java并发容器,让我们更好的使用并发容器打造更高效的程序.本人能力有限,错误难免.希望及时指出. ...
- Java并发包源码学习系列:阻塞队列BlockingQueue及实现原理分析
目录 本篇要点 什么是阻塞队列 阻塞队列提供的方法 阻塞队列的七种实现 TransferQueue和BlockingQueue的区别 1.ArrayBlockingQueue 2.LinkedBloc ...
- java并发包&线程池原理分析&锁的深度化
java并发包&线程池原理分析&锁的深度化 并发包 同步容器类 Vector与ArrayList区别 1.ArrayList是最常用的List实现类,内部是通过数组实现的, ...
- HashMap、Hashtable、ConcurrentHashMap、ConcurrentSkipListMap对比及java并发包(java.util.concurrent)
一.基础普及 接口(interface) 类(class) 继承类 实现的接口 Array √ Collection √ Set √ Collection List √ Collection Map ...
- Java并发包源码学习系列:线程池ThreadPoolExecutor源码解析
目录 ThreadPoolExecutor概述 线程池解决的优点 线程池处理流程 创建线程池 重要常量及字段 线程池的五种状态及转换 ThreadPoolExecutor构造参数及参数意义 Work类 ...
- [Java 基础] 并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue用法
reference : http://www.cnblogs.com/linjiqin/archive/2013/05/30/3108188.html 在Java多线程应用中,队列的使用率很高,多数生 ...
随机推荐
- Selenium2+python自动化46-js解决click失效问题【转载】
前言 有时候元素明明已经找到了,运行也没报错,点击后页面没任何反应.这种问题遇到了,是比较头疼的,因为没任何报错,只是click事件失效了. 本篇用2种方法解决这种诡异的点击事件失效问题 一.遇到的问 ...
- python算法:LinkedList(双向线性链表)的实现
LinkedList是一个双向线性链表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer).由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一 ...
- 官方文档,才是正途-docker-compose
需要的ingress网络映射,还是host宿主机端口映射: https://docs.docker.com/compose/compose-file/#secrets ================ ...
- ubuntu下执行ulimit返回“不允许的操作”,问题解决思路
在ubuntu下执行ulimit,希望修改允许的最大打开文件数,但返回“不允许的操作”. 使用ulimit -a查看当前配置 core file size (blocks, -c) 0 data se ...
- [ThinkPHP] 模板输出 时间格式 Unix时间戳
{$create_time|date="y-m-d",###}
- HDU 6357.Hills And Valleys-字符串非严格递增子序列(LIS最长非下降子序列)+动态规划(区间翻转l,r找最长非递减子序列),好题哇 (2018 Multi-University Training Contest 5 1008)
6357. Hills And Valleys 自己感觉这是个好题,应该是经典题目,所以半路选手补了这道字符串的动态规划题目. 题意就是给你一个串,翻转任意区间一次,求最长的非下降子序列. 一看题面写 ...
- python sql语句封装连接mysql
进行了代码优化,欢迎评审 #!/usr/bin/python # -*- coding:utf-8 -*- import logging logging.basicConfig(level=loggi ...
- 【AC自动机】zoj3228 Searching the String
对所有模式串建立AC自动机. 每个单词结点要记录该单词长度. 然后在跑匹配的时候,对每个单词结点再处理3个值,代表可重叠的匹配次数,不可重叠的匹配次数,以及“上一次不可重叠的匹配位置”,这样结合单词长 ...
- 【匈牙利算法】BZOJ1059-[ZJOI2007]矩阵游戏
[题目大意] 给出一个局部染色的矩阵,问能否通过交换行或者列使得最后又一条对角线全部被染色过? [思路] 无论如何交换,同一行的格子依然在同一行,同一列的格子依然在同一列.所以只需找出n个行号列号均不 ...
- python基础-文件处理与函数
1. 文件处理 1.1 文件处理流程 1.打开文件,得到文件句柄并赋值给一个变量 2.通过句柄对文件进行操作 3.关闭文件 1.2 文件读取模式r r文本模式的读,在文件不存在,不会创建新文件 f = ...