直接上代码: 前提是你已经 熟悉了原子类,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. Windows核心编程 第五章 作业(上)

    第5章 作 业 通常,必须将一组进程当作单个实体来处理.例如,当让 Microsoft Developer Studio为你创建一个应用程序项目时,它会生成 C l . e x e,C l . e x ...

  2. js中return;、return true、return false;区别

    一.返回控制与函数结果 语法为:return 表达式 语句结束函数执行,返回调用函数,而且把表达式的值作为函数的结果 二.返回控制 无函数结果,语法为:return; 在大多数情况下,为事件处理函数返 ...

  3. xxl-job滥用netty导致的问题和解决方案

    netty作为一种高性能的网络编程框架,在很多开源项目中大放异彩,十分亮眼,但是在有些项目中却被滥用,导致使用者使用起来非常的难受. 本篇文章将会讲解xxl-job作为一款分布式任务调度系统是如何滥用 ...

  4. 安装google cloud sdk报错解决方法总结(超全)

    前提:python环境最好是2.7,如果是python3可能会出很多小毛病:能用64位系统就尽量用64位,32位系统安装也很多毛病 一.Error1:Unzip Failed: Error openi ...

  5. 码农飞升记-02-OracleJDK是什么?OracleJDK的版本怎么选择?

    目录 1.Oracle JDK 是什么? 2.Oracle JDK 版本如何选择? 1.Java SE 发布节奏以及不同版本的差距 1.Java SE 8 以及之前版本的发布节奏和不同版本的差距 1. ...

  6. CLS的探索:Python如何让日志免费云化

    前言 日志服务(Cloud Log Service,CLS)是腾讯云提供的一站式日志服务平台,提供了从日志采集.日志存储到日志检索,图表分析.监控告警.日志投递等多项服务,协助用户通过日志来解决业务运 ...

  7. 【近取 key】Alpha 阶段任务分配

    项目 内容 这个作业属于哪个课程 2021春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 alpha阶段初始任务分配 我在这个课程的目标是 进一步提升工程化开发能力,积累团队协作经验,熟悉 ...

  8. 名称空间 反向解析 reverse

  9. mac SSH私钥取消密码(passphrase)

    取消私钥中的密码: 1.使用openssl命令去掉私钥的密码openssl rsa -in ~/.ssh/id_rsa -out ~/.ssh/id_rsa_new 2.备份旧私钥mv ~/.ssh/ ...

  10. FastDFS依赖无法导入

    FastDFS依赖无法导入 fastdfs-client-java 导入爆红 <!-- FastDFS--> <dependency> <groupId>org.c ...