一、BlockingQueue简介?
阻塞队列BlockingQueue顾名思义是一个队列,在多线程环境中可以通过队列非常方便的实现数据共享。比如常规的“生产者”、“消费者”模型中,常常会出现生产者、消费者数据处理速度不匹配的情况,当生产者产生数据速度过快,那么必须阻塞生产者线程,以便等待消费者线程把累积的数据处理完毕。在多线程环境下,程序员自己控制这些细节显得十分复杂,尤其还要兼顾效率和线程安全,使用BlockingQueue就简化了这个问题。不需要再关心什么时候需要阻塞线程,什么时候需要唤醒线程了。
二 、开发实例
下面代码是在spring框架下使用BlockingQueue实现短信发送功能
@Service
public class NotifyQueueService {
@Autowired
NotifyService notifyService;
private static BlockingQueue<Runnable> runnableQueue;
private static BlockingQueue<NotifyMsg> notifyQueue;
private static ThreadPoolExecutor threadPoolExecutor;
private static Thread noticThread;
/*项目启动时初始化线程池,线程队列及消息队列,这里队列使用LinkedBlockingQueue实现类
并启动监听线程及时消费。
*/
@PostConstruct
public void init() {
if (notifyQueue== null) {
notifyQueue = new LinkedBlockingQueue<NotifyMsg>(); // 消息延时发送队列
}
if (runnableQueue == null) {
runnableQueue = new LinkedBlockingQueue<Runnable>();//线程池链表的阻塞队列
}
if (threadPoolExecutor == null) {
// 线程池初始化,核心线程设为10,普通线程最大30,超时回收时间10秒
threadPoolExecutor = new ThreadPoolExecutor(10, 30, 10,
TimeUnit.SECONDS, runnableQueue);//线程池初始化设置,将线程池队列传入
}
if (noticThread== null) {
noticThread= new Thread(new Runnable() {//实例化守护线程监听队列信息
@Override
public void run() {
while (true) {
try {
//从队列中取出消息线程池启动发送信息线程
threadPoolExecutor.execute(new sendMsg(
notifyQueue.take()));
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
noticThread.setDaemon(true);//设置为守护线程
noticThread.setName("noticThread");//命名
noticThread.start();//开启守护线程监听队列消息
}
}
putData方法供其他消息生产者调用,用于往消息队列中插入信息。
// 往消息队列中塞入消息
public void putData(NoticMsg noticMsg) {
if (noticMsg!= null) {
notifyQueue.offer(noticMsg);// 生产者放入队列
}
}
sendMsg类用于消费信息队列中的信息。
/**
*
* 消费线程
*
*/
public class sendMsg implements Runnable {
private NoticMsg noticMsg;
public sendMsgUnit(NoticMsg noticMsg ) {
super();
this.noticMsg = noticMsg ;
}
@Override
public void run() {
try {
logger.info("启动了一个发送线程");
if (noticMsg != null) {
//调用短信发送方法,发送短信。
notifyService.notify(noticMsg);
}
} catch (Exception e) {
e.printStackTrace();
logger.info("发送短信失败");
}
}
}