java线程(7)——阻塞队列BlockingQueue
回顾:
阻塞队列,英文名叫BlockingQueue。首先他是一种队列,联系之前Java基础——集合中介绍的Queue与Collection,我们就很容易开始今天的阻塞队列的学习了。来看一下他们的接口定义:
Queue:
(方法很简单,就不一一注释解释其作用了。)
public interface Queue<E> extends Collection<E> {
boolean add(E e);
boolean offer(E e);
E remove();
E poll();
E element();
E peek();
}
BlockingQueue:
因为是继承自Queue,方法基本类似,就不再写了。主要方法有三个:add,remove,element(用于检查)。
那到底什么是阻塞队列呢?联系前面java线程——模拟生产者与消费者的例子,在篮子中没有馒头时,生成者要放入馒头消费者才能食用;在篮子里装满馒头时,生产者就不能继续生产了,要等人去吃。阻塞队列就是生产者存放馒头的容器,消费者从中取出元素,也就是那个篮子。
public interface BlockingQueue<E> extends Queue<E> {
......
}
BlockingQueue的实现类有很多,这里介绍一个很简单的ArrayBlockingQueue。他是一个数据结构组成的阻塞队列,按照FIFO先进先出的方式排序。
继续来看他的定义,下面只列举了常用的两个方法:
public class ArrayBlockingQueue<E> extends AbstractQueue<E>
implements BlockingQueue<E>, java.io.Serializable { //放入元素
public void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == items.length)
notFull.await();
enqueue(e);
} finally {
lock.unlock();
}
} //取元素
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0)
notEmpty.await();
return dequeue();
} finally {
lock.unlock();
}
}
}
来个例子:
//Capacity为3的阻塞队列
final BlockingQueue queue = new ArrayBlockingQueue(3);
for (int i = 0; i < 2; i++) {
//1、放馒头线程
new Thread() { @Override
public void run() {
while (true) { try {
Thread.sleep((long) (Math.random() * 10000));
System.out.println(Thread.currentThread().getName()
+ "准备放馒头!");
//每次放入一个馒头
queue.put(1);
System.out.println(Thread.currentThread().getName()
+ "已经放了馒头," + "队列目前有" + queue.size()
+ "个馒头");
} catch (InterruptedException e) { e.printStackTrace();
}
}
} }.start();
}
//2、取馒头线程
new Thread() { @Override
public void run() {
while (true) {
try { Thread.sleep((long) (Math.random() * 10000));
System.out.println(Thread.currentThread().getName()
+ "准备取馒头!");
//拿走一个
queue.take();
System.out.println(Thread.currentThread().getName()
+ "已经取走馒头," + "队列目前有" + queue.size() + "个馒头");
} catch (InterruptedException e) { e.printStackTrace();
}
}
} }.start(); }
部分执行结果:
对比:
和之前手动实现生产者消费者的例子相比,这次的实现就简单多了。不再需要去管篮子里的“取”和“放”的操作,不用关心线程的同步互斥问题,不用关心篮子是空了还是满了。只需要简单的调用put或take方法即可,把复杂的阻塞问题教给BlockingQueue去处理,但是原理还是一样的。
java线程(7)——阻塞队列BlockingQueue的更多相关文章
- Java并发编程-阻塞队列(BlockingQueue)的实现原理
背景:总结JUC下面的阻塞队列的实现,很方便写生产者消费者模式. 常用操作方法 常用的实现类 ArrayBlockingQueue DelayQueue LinkedBlockingQueue Pri ...
- java并发包——阻塞队列BlockingQueue及源码分析
一.摘要 BlockingQueue通常用于一个线程在生产对象,而另外一个线程在消费这些对象的场景,例如在线程池中,当运行的线程数目大于核心的线程数目时候,经常就会把新来的线程对象放到Blocking ...
- Java并发编程——阻塞队列BlockingQueue
Java 并发编程系列文章 Java 并发基础——线程安全性 Java 并发编程——Callable+Future+FutureTask java 并发编程——Thread 源码重新学习 java并发 ...
- Java并发(十八):阻塞队列BlockingQueue
阻塞队列(BlockingQueue)是一个支持两个附加操作的队列. 这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空.当队列满时,存储元素的线程会等待队列可用. 阻塞队列常用于生产 ...
- Java并发指南11:解读 Java 阻塞队列 BlockingQueue
解读 Java 并发队列 BlockingQueue 转自:https://javadoop.com/post/java-concurrent-queue 最近得空,想写篇文章好好说说 java 线程 ...
- java线程自带队列的使用以及线程阻塞
java线程,设置队列的大小实现队列阻塞 public class QueueThreads { private static int nThreads = 4;//Runtime.getRuntim ...
- Java中的阻塞队列(BlockingQueue)
1. 什么是阻塞队列 阻塞队列(BlockingQueue)是 Java 5 并发新特性中的内容,阻塞队列的接口是 java.util.concurrent.BlockingQueue,它提供了两个附 ...
- spring线程池ThreadPoolTaskExecutor与阻塞队列BlockingQueue
一: ThreadPoolTaskExecutor是一个spring的线程池技术,查看代码可以看到这样一个字段: private ThreadPoolExecutor threadPoolExecut ...
- Java阻塞队列(BlockingQueue)实现 生产者/消费者 示例
Java阻塞队列(BlockingQueue)实现 生产者/消费者 示例 本文由 TonySpark 翻译自 Javarevisited.转载请参见文章末尾的要求. Java.util.concurr ...
- Java中的阻塞队列
1. 什么是阻塞队列? 阻塞队列(BlockingQueue)是一个支持两个附加操作的队列.这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空.当队列满时,存储元素的线程会等待队列可用 ...
随机推荐
- CF605A Sorting Railway Cars(递推)
题目描述 An infinitely long railway has a train consisting of n cars, numbered from 1 to n (the numbers ...
- HDU 6354--Everything Has Changed(判断两圆关系+弧长计算)
题目 题意:首先给定一个以原点为圆心,R为半径的圆,之后在给m个圆,这些圆可能会和原来的圆有所交集,计算开始的圆剩余区域的周长,不包括内部周长. 首先判定两圆关系,如果内含,直接加上圆的周长,如果相交 ...
- Linux计算某一列的和
ll | awk '{print $5}' | egrep -v "^$"| paste -sd+|bc 简单说明: ll:拿到当前目录下所有的文件大小 awk:拿到第几列 egr ...
- flask之请求钩子
from flask import Flask from flask import abort app = Flask(__name__) # 在第一次请求之前调用,可以在此方法内部做一些初始化操作 ...
- MySQL数据库常见报错原因
1.启动数据库时报错 启动 # /etc/init.d/mysqld start Starting MySQL.Logging to '/application/mysql-5.6.36/data/m ...
- git 上传到码云
创建分支 在码云里创建好分支 命令行进入项目所在的目录 显示码云上的分支 git pull 选择将要编辑的分支(index-fenzhi) git checkout index-fenzhi 查看分支 ...
- 配置Github秘钥
Git安装完成后,需要手动配置ssh密钥 配置github的ssh密钥: (1)打开Git Bash查看电脑上是否已经存在SSH密钥: 输入 cd ~/.ssh 若如上图显示无法找到该文件则要创建新的 ...
- 学习新框架laravel 5.6 (第一天)
学习新框架第一天. composer 基本命令: composer list 获取帮助信息 composer init 以交互方式填写composer.json文件信息 composer instal ...
- Volatile的详解
volatile关键字修饰的共享变量主要有两个特点:1.保证了不同线程访问的内存可见性 2.禁止重排序 在说内存可见性和有序性之前,我们有必要看一下Java的内存模型(注意和JVM内存模型的区分 ...
- 网站标题被篡改成北京赛车、PK10的解决处理办法
客户网站于近日被跳转到赌博网站,打开后直接跳转到什么北京赛车,PK10等内容的网站上去,客户网站本身做了百度的推广,导致所有访问用户都跳转到赌博网站上去,给客户带来很大的经济损失,再一个官方网站的形象 ...