博客
关于我
java同步代码(synchronized)中使用BlockingQueue
阅读量:633 次
发布时间:2019-03-14

本文共 4522 字,大约阅读时间需要 15 分钟。

说起BlockingQueue,大家最熟悉的就是生产者-消费者模式下的应用。但是如果在调用queue的上层代码加了同步块就会导致线程死锁。

例如:

static BlockingQueue
queue = new LinkedBlockingQueue(); /** * 同步锁 */ static Object lock = new Object(); static void producer(){ synchronized (lock){ queue.put("1"); } } static void cosumer(){ synchronized (lock){ //一旦阻塞,将挂起当前线程,lock锁永远等不到释放,生产者也就无法添加元素,take也就永远阻塞 String msg = queue.take(); } }

但是同步块必须使用的情况下,怎样改进queue的使用呢?见下面示例:

package com.hdwang;import com.alibaba.fastjson.JSON;import java.util.concurrent.BlockingQueue;import java.util.concurrent.LinkedBlockingQueue;/** * Created by hdwang on 2018/4/17. */public class MultiQueueSynTest {    static BlockingQueue
queue1 = new LinkedBlockingQueue(); static BlockingQueue
queue2 = new LinkedBlockingQueue(); static int seq = 1; /** * 同步锁 */ static Object lock = new Object(); static void commit(String msg){ synchronized (lock) { Packet packet = new Packet(); packet.setSeq(seq++); packet.setMsg(msg); try { //queue1.put(packet); //阻塞式添加元素 while(queue1.size()== Integer.MAX_VALUE){ //队满,等待 lock.wait(); } queue1.offer(packet); //非阻塞式添加元素即可 System.out.println("commit msg:" + JSON.toJSONString(packet)); lock.notifyAll(); //通知等待线程 } catch (InterruptedException e) { e.printStackTrace(); } } } static void send(){ while(true) { synchronized (lock) { try { //Packet packet = queue1.take(); //阻塞式取元素 //queue2.put(packet); while(queue1.isEmpty()) { //队空,等待 lock.wait(); //等待,交出锁 } Packet packet = queue1.poll(); //非阻塞式取元素即可 System.out.println("send msg:" + JSON.toJSONString(packet)); lock.notifyAll(); //通知等待线程 while (queue2.size() == Integer.MAX_VALUE){ //队满,等待 lock.wait(); //等待,交出锁 } queue2.offer(packet); System.out.println("msg->queue2:"+JSON.toJSONString(packet)); lock.notifyAll(); //通知等待线程 } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) { //生产者1 new Thread(new Runnable() { @Override public void run() { while(true){ //不断产生消息 commit("hello1"); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); //生产者2 new Thread(new Runnable() { @Override public void run() { while(true){ //不断产生消息 commit("hello2"); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); //消费者 new Thread(new Runnable() { @Override public void run() { send(); } }).start(); } static class Packet{ int seq; String msg; public int getSeq() { return seq; } public void setSeq(int seq) { this.seq = seq; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } }}

运行结果

commit msg:{"msg":"hello1","seq":1}send msg:{"msg":"hello1","seq":1}msg->queue2:{"msg":"hello1","seq":1}commit msg:{"msg":"hello2","seq":2}send msg:{"msg":"hello2","seq":2}msg->queue2:{"msg":"hello2","seq":2}commit msg:{"msg":"hello1","seq":3}send msg:{"msg":"hello1","seq":3}msg->queue2:{"msg":"hello1","seq":3}commit msg:{"msg":"hello2","seq":4}send msg:{"msg":"hello2","seq":4}msg->queue2:{"msg":"hello2","seq":4}commit msg:{"msg":"hello1","seq":5}send msg:{"msg":"hello1","seq":5}msg->queue2:{"msg":"hello1","seq":5}commit msg:{"msg":"hello2","seq":6}send msg:{"msg":"hello2","seq":6}msg->queue2:{"msg":"hello2","seq":6}

 

转载地址:http://fptoz.baihongyu.com/

你可能感兴趣的文章
mysql加强(5)~DML 增删改操作和 DQL 查询操作
查看>>
mysql加强(6)~子查询简单介绍、子查询分类
查看>>
MySQL单实例或多实例启动脚本
查看>>
MySQL压缩包方式安装,傻瓜式教学
查看>>
MySQL原理、设计与应用全面解析
查看>>
MySQL原理简介—1.SQL的执行流程
查看>>
mysql参考触发条件_MySQL 5.0-触发器(参考)_mysql
查看>>
MySQL及navicat for mysql中文乱码
查看>>
MySqL双机热备份(二)--MysqL主-主复制实现
查看>>
mysql启动以后会自动关闭_驾照虽然是C1,一直是开自动挡的车,会不会以后就不会开手动了?...
查看>>
mysql启动和关闭外键约束的方法(FOREIGN_KEY_CHECKS)
查看>>
Mysql启动失败解决过程
查看>>
MySQL启动失败:Can't start server: Bind on TCP/IP port
查看>>
mysql启动报错
查看>>
mysql启动报错The server quit without updating PID file几种解决办法
查看>>
mysql和oorcale日期区间查询【含左右区间问题】
查看>>
MySQL和SQL入门
查看>>
mysql在centos下用命令批量导入报错_Variable ‘character_set_client‘ can‘t be set to the value of ‘---linux工作笔记042
查看>>
Mysql在Linux运行时新增配置文件提示:World-wrirable config file ‘/etc/mysql/conf.d/my.cnf‘ is ignored 权限过高导致
查看>>
Mysql在Windows上离线安装与配置
查看>>