直接上代码: 前提是你已经 熟悉了原子类,volatile,和阻塞队列

public class JucPCdemo03 {
/**
* 阻塞队列的应用: 这里实现的生产者消费者,生产一个消费一个
* 且,不使用 synchronized 和 lock锁
*/
private volatile boolean flag = true;
private static AtomicInteger atomicInteger = new AtomicInteger(0);
private BlockingQueue<String> blockingQueue; public JucPCdemo03(BlockingQueue<String> blockingQueue) {
this.blockingQueue = blockingQueue;
System.out.println(blockingQueue.getClass().getName());
} //生产方法
public void producer() throws InterruptedException {
String data = null;
boolean result;
while(flag){
data = atomicInteger.incrementAndGet()+"";
result = blockingQueue.offer(data, 2, TimeUnit.SECONDS);
if(result){
System.out.println(Thread.currentThread().getName() + "--生产者--添加队列成功--data:" + data);
}else{
System.out.println(Thread.currentThread().getName() + "--生产者--超出等待时间, 退出等待");
}
//我在这里有疑惑? : 你能帮我解决么?
// 这里睡1秒,不能少,因为 atomicInteger加1的操作是原子的,加入阻塞队列的操作是并发的,会导致同一时间内,有多个元素加入到了阻塞队列中,返回都是true,即使规定阻塞队列容量为1,
// 所以这里的疑惑是: 阻塞队列容量为1, 并发情况下,却多个数据都加入队列成功了?为什么
TimeUnit.SECONDS.sleep(1);
} System.out.println();
System.out.println();
System.out.println();
System.out.println("生产者停止生产了");
}
//消费方法
public void consumer() throws InterruptedException {
String data = null;
while(flag){
data = blockingQueue.poll(2, TimeUnit.SECONDS);
if(null == data || "".equals(data)){
System.out.println(Thread.currentThread().getName() + "--消费者--超出等待时间.退出等待,消费停止");
flag = false;
return;
}else{
System.out.println(Thread.currentThread().getName() + "--消费者--消费成功,消费的数据为: data:" + data);
}
}
System.out.println();
System.out.println();
System.out.println();
System.out.println("消费者停止消费了");
}
public void stop(){
flag = false;
} public static void main(String[] args) throws InterruptedException {
JucPCdemo03 jucPCdemo03 = new JucPCdemo03(new ArrayBlockingQueue<>(1)); new Thread(()->{
try {
jucPCdemo03.producer();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"生产者线程启动").start(); new Thread(()->{
try {
jucPCdemo03.consumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"消费者线程启动").start(); TimeUnit.SECONDS.sleep(5);
jucPCdemo03.stop();
}
}

运行结果:

如果把生产者的 睡一秒, 注释掉, 会是另一种结果, 生产者生产的data 都很大,是因为一直再while循环中,不停的自增, 但是同时3个数据加入队列成功,可是队列的容量设置是1啊, 这个结果让我有些疑惑, 你能帮我解惑么?

后来想到: 阻塞队列类本身是juc包下的, 肯定是原子性操作的, 所以他的容量前后都是始终为1, 是因为 "生产者线程启动--生产者--添加队列成功--data:269209" 这句话打印,这里并发打印了, 所以给我看到的假象多个数据都加入阻塞队列成功了, 于是验证: 加一行代码,



运行结果为: 队列容量始终为1, "生产者线程启动--生产者--添加队列成功--data:269209" 这句话有时候打印三次,有时候打印一次,很明显验证了我的结论

JUC 并发编程--07 阻塞队列版本的 生产者消费者(不使用synchronized和 lock),也有一些疑惑,最终解惑的更多相关文章

  1. 用阻塞队列实现一个生产者消费者模型?synchronized和lock有什么区别?

    多线程当中的阻塞队列 主要实现类有 ArrayBlockingQueue是一个基于数组结构的有界阻塞队列,此队列按FIFO原则对元素进行排序 LinkedBlockingQueue是一个基于链表结构的 ...

  2. JUC 并发编程--10, 阻塞队列之--LinkedBlockingDeque 工作窃取, 代码演示

    直接上代码 class LinkedBlockingDequeDemo { // 循环是否结束的开关 private static volatile boolean flag1 = true; pri ...

  3. JUC 并发编程--09, 阻塞队列: DelayQueue, PriorityBlockingQueue ,SynchronousQueue, 定时任务线程池: ScheduledThreadPoolExecutor

    先看DelayQueue 这个是用优先级队列实现的无界限的延迟队列,直接上代码: /** * 这个是 {@link DelayQueue} 延时队列 的验证使用类 */ class MyDelayed ...

  4. JUC 并发编程--06, 阻塞队列(7种), 阻塞等待 api的 代码验证

    这些队列的 api ,就是添加队列,出队列,检测对首元素, 由于 add()--remove(), offer()--poll(),太简单这里不做验证, 只验证后二组api: 阻塞等待( put()- ...

  5. java并发编程:阻塞队列

    一.几种主要的阻塞队列 自从Java 1.5之后,在java.util.concurrent包下提供了若干个阻塞队列,主要有以下几个: ArrayBlockingQueue:基于数组实现的一个阻塞队列 ...

  6. Java并发编程:阻塞队列(转载)

    Java并发编程:阻塞队列 在前面几篇文章中,我们讨论了同步容器(Hashtable.Vector),也讨论了并发容器(ConcurrentHashMap.CopyOnWriteArrayList), ...

  7. 【转】Java并发编程:阻塞队列

    在前面几篇文章中,我们讨论了同步容器(Hashtable.Vector),也讨论了并发容器(ConcurrentHashMap.CopyOnWriteArrayList),这些工具都为我们编写多线程程 ...

  8. Java并发编程:阻塞队列 <转>

    在前面几篇文章中,我们讨论了同步容器(Hashtable.Vector),也讨论了并发容器(ConcurrentHashMap.CopyOnWriteArrayList),这些工具都为我们编写多线程程 ...

  9. 12、Java并发编程:阻塞队列

    Java并发编程:阻塞队列 在前面几篇文章中,我们讨论了同步容器(Hashtable.Vector),也讨论了并发容器(ConcurrentHashMap.CopyOnWriteArrayList), ...

随机推荐

  1. UVA11039

    题意:      给你一个序列,由n个数字组成,每个数字的绝对值都不相同,然后让你从这n个数中拿出一些数,组成一个绝对值递增并且正负交替的最大序列,问组成的最大序列的最大长度是多少? 思路:     ...

  2. Windows PE 第一章开发环境和基本工具使用

    第一章 Windows PE 基本工具 1.1开发语言MASM32 1.1.1设置开发环境 这个不细说了,我在整理Intel汇编的时候详细的说了环境搭建以及细节.地址是:http://blog.csd ...

  3. 死磕到底RecyclerView | RecyclerView 的滚动是怎么实现的?

    RecyclerView 是一个展示列表的控件,其中的子控件可以被滚动.这是怎么实现的?以走查源码的方式一探究竟. 切入点:滚动事件 阅读源码时,如何在浩瀚的源码中选择合适的切入点很重要,选好了能少走 ...

  4. <JVM下篇:性能监控与调优篇>01-概述篇-02-JVM监控及诊断工具-命令行篇

    笔记来源:尚硅谷JVM全套教程,百万播放,全网巅峰(宋红康详解java虚拟机) 同步更新:https://gitee.com/vectorx/NOTE_JVM https://codechina.cs ...

  5. Mybatis 遍历 List<Map<String,Object>>

    在上一篇博客中总结了MyBatis Plus 实现多表分页模糊查询(链接在最后).返回类型是编写一个专门的vo类.这次是返回List < Map > 前言 ​ 编写一个专门的vo返回类,主 ...

  6. CCNA 第一章 网络互联

    1: 网络互联基础 互联网络定义:使用路由器将多个网络连接起来,并配置IP或者IPV6协议的逻辑网络编址方案,便组成了互联网络. 导致LAN(局域网)拥塞的常见原因: (1):广播域或者冲突域中的主机 ...

  7. JS阻止冒泡事件

    <!DOCTYPE html><html><head> <title></title> <style type="text/ ...

  8. Python中的迭代器、生成器、装饰器

    1. 迭代器  1 """ 2 iterator 3 迭代器协议: 对象必须提供一个next()方法,执行该方法要么返回迭代中的下一项,要么引起一个StopIterati ...

  9. [源码解析] 并行分布式任务队列 Celery 之 负载均衡

    [源码解析] 并行分布式任务队列 Celery 之 负载均衡 目录 [源码解析] 并行分布式任务队列 Celery 之 负载均衡 0x00 摘要 0x01 负载均衡 1.1 哪几个 queue 1.1 ...

  10. Linux Limit相关内容设置大全(值得收藏)

    目录 一. /etc/security/limits.conf 详解 /etc/security/limits.conf 配置解析 /etc/security/limits.d/目录 二. ulimi ...