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

例如:

    static BlockingQueue<String> 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<Packet> queue1 = new LinkedBlockingQueue(); static BlockingQueue<Packet> 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}

java同步代码(synchronized)中使用BlockingQueue的更多相关文章

  1. wait、notify为什么要放在同步代码块中

    等待方遵循的原则: 获取对象的锁,不满足条件就调用wait()方法,条件满足继续执行 通知方原则: 获取对象的锁,改变条件,然后notify 每个对象都有一个监视器锁,这个监视器锁的数据结构如下: w ...

  2. .NET中如何在同步代码块中调用异步方法

    更新记录 本文迁移自Panda666原博客,原发布时间:2021年7月2日. 在同步代码块中调用异步方法,方法有很多. 一.对于有返回值的Task 在同步代码块中直接访问 Task 的 Result ...

  3. JAVA 同步之 synchronized 修饰方法

    在JAVA多线程编程中,将需要并发执行的代码放在Thread类的run方法里面,然后创建多个Thread类的对象,调用start()方法,线程启动执行. 当某段代码需要互斥时,可以用 synchron ...

  4. java 同步代码块与同步方法

    同步代码块 synchronized (obj) { // 代码块 } obj 为同步监视器,以上代码的含义为:线程开始执行同步代码块(中的代码)之前,必须先获得对同步监视器的锁定. 代码块中的代码是 ...

  5. Java 同步代码块 - Synchronized Blocks

    java锁实现原理: http://blog.csdn.net/endlu/article/details/51249156 The synchronized keyword can be used ...

  6. JAVA之旅(十三)——线程的安全性,synchronized关键字,多线程同步代码块,同步函数,同步函数的锁是this

    JAVA之旅(十三)--线程的安全性,synchronized关键字,多线程同步代码块,同步函数,同步函数的锁是this 我们继续上个篇幅接着讲线程的知识点 一.线程的安全性 当我们开启四个窗口(线程 ...

  7. 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁

    什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程的三种方式示例代码中,实现Runnable创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...

  8. Java线程同步(synchronized)——卖票问题

    卖票问题通常被用来举例说明线程同步问题,在Java中,采用关键字synchronized关键字来解决线程同步的问题. Java任意类型的对象都有一个标志位,该标志位具有0,1两种状态,其开始状态为1, ...

  9. java并发之线程同步(synchronized和锁机制)

    使用synchronized实现同步方法 使用非依赖属性实现同步 在同步块中使用条件(wait(),notify(),notifyAll()) 使用锁实现同步 使用读写锁实现同步数据访问 修改锁的公平 ...

随机推荐

  1. c# thread pause example

    some times we need pause thread to do some additional job: c# thread pause example as below: 1. crea ...

  2. python基础2之字符串、列表、字典、集合

    内容概要: 一.python2 or 3 二.字符串拼接 三.字符串 四.列表.元祖 五.字典 六.集合 七.练习 一.python2 or python3 目前大多使用python2.7,随着时间的 ...

  3. 20155304田宜楠《网络对抗技术》Exp1 PC平台逆向破解(5)M

    Exp1 PC平台逆向破解(5)M 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串. 该程序 ...

  4. 20155337 《网络对抗》 Exp2 后门原理与实践

    20155337 <网络对抗> Exp2 后门原理与实践 一.基础问题回答 - 例举你能想到的一个后门进入到你系统中的可能方式? 在Unix里,login程序通常用来对telnet来的用户 ...

  5. python中的-1

    -1单个使用时表示最后一个: >>> [1,2,3,4][-1] 4 表示范围(区间)时,因为是开区间表示方法,如[0:2]是不包括2的所以 [0:-1]只能访问到倒数第二个(不包括 ...

  6. CodeForces-1155D Beautiful Array

    Description You are given an array \(a\) consisting of \(n\) integers. Beauty of array is the maximu ...

  7. kali黑客渗透测试基础环境准备

    1.apt-get install python-nmap 2.apt-get install python-setuptools 正在读取软件包列表... 完成 正在分析软件包的依赖关系树      ...

  8. Flask_admin 笔记一 (快速启用)

    1,快速启用   1) 安装flask-admin pip install flask-admin 2) 配置使用 from flask import Flask from flask_admin i ...

  9. 虚拟机console最小化安装操作系统图文

    1. 概述2. 安装操作系统2.1 交互界面2.2 内核镜像解压等初始化2.3 磁盘发现2.4 硬件支持告警3. 开始安装3.1 语言选择3.2 键盘选择3.3 服务器类型3.4 配置主机名3.5 时 ...

  10. MOSFET简介以及PMOS和NMOS的差异

    最近在工作中,一直在调试关于MOSFET的电路.在设计过程中发现了PMOS和NMOS的差异,在此记录. 一. MOSFET简介 MOSFET (metal-oxide-semiconductor fi ...