队列分为两类

 阻塞队列

BlockingQueue提供如下两个支持阻塞的方法:

  (1)put(E e): 尝试把e元素放如BlockingQueue中,如果该队列的元素已满,则阻塞该线程。

  (2)take(): 尝试从BlockingQueue的头部取出元素,如果该队列的元素已空,则阻塞该线程。

jdk实现的有以下几种:

ArrayBlockingQueue,底层是数组,有界队列

LinkedBlockingQueue,,底层是链表,无界队列

PriorityBlockingQueue,一个带优先级的队列,上put时是不会受阻的,但是如果队列为空,取元素的操作take就会阻塞。另外,往入该队列中的元 素要具有比较能力。

PriorityBlockingQueue里面存储的对象必须是实现Comparable接口。队列通过这个接口的compare方法确定对象的priority。 【下面会有代码举例说明】

SynchronousQueue 是一个没有数据缓冲的阻塞队列,(只能存储一个元素)准确的说 他不存储元素,放入元素必须等待取走以后,才能放入新的元素

    但它的特别之处在于它内部没有容器,一个生产线程,当它生产产品(即put的时候),如果当前没有人想要消费产品(即当前没有线程执行take),此生产线程必须阻塞,等待一个消费线程调用take操作,take操作将会唤醒该生产线程,同时消费线程会获取生产线程的产品(即数据传递),这样的一个过程称为一次配对过程(当然也可以先take后put,原理是一样的)。另外他是直接使用CAS实现线程的安全访问(jdk8)。

DelayQueue, 只有在队列中的元素到期后才能取出。里面存储的对象必须实现Delayed接口,里面有两个方法【下面会有代码举例说明】

 非阻塞队列

ConcurrentLinkedQueue 性能最好,是一个无界队列

add 和 offer都是加入元素方法(没有差别)

poll和peek都是获取头元素的方法,区别在于前者会删除元素,后者不会删除

下面举例说明PriorityBlockingQueue 和 DelayQueue的用法

/**
* PriorityBlockingQueue测试
*
*
*/
public class TestPriorityQueue2 {
public static void main(String[] args) throws InterruptedException {
PriorityBlockingQueue<Student> priorityBlockingQueue=new PriorityBlockingQueue<>();
priorityBlockingQueue.put(new Student("stu1",2));
priorityBlockingQueue.put(new Student("stu2",3));
priorityBlockingQueue.put(new Student("stu3",2));
priorityBlockingQueue.put(new Student("stu4",4)); System.out.println(priorityBlockingQueue.take().toString());
}
}
class Student implements Comparable<Student> {
private String name;
private Integer age; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Integer getAge() {
return age;
} public void setAge(Integer age) {
this.age = age;
} public Student(String name, Integer age) {
this.name = name;
this.age = age;
} // //正序
// @Override
// public int compareTo(Student o) {
// return this.age>o.age?1:this.age<o.age?-1:0;
// } //逆序
@Override
public int compareTo(Student o) {
return this.age<o.age?1:-1;
}
@Override
public String toString() {
return "Student{" +
"name=" + name + ", age=" + age + '}';
} }

  接下来是DelayQueue,主要应用场景有以下几个

1) 关闭空闲连接。服务器中,有很多客户端的连接,空闲一段时间之后需要关闭之。
2) 缓存。缓存中的对象,超过了空闲时间,需要从缓存中移出。
3) 任务超时处理。在网络协议滑动窗口请求应答式交互时,处理超时未响应的请求。

下面举一个例子

public class Wangming implements Delayed {

	private String name;
// 截止时间
private long endTime; public Wangming(String name, String id, long endTime) {
this.name = name;
this.endTime = endTime;
} public Wangming(String name, long endTime) {
this.name = name;
this.endTime = endTime;
} public String getName() {
return this.name;
} /**
* 用来判断是否到了截止时间
*/
@Override
public long getDelay(TimeUnit unit) {
return endTime - System.currentTimeMillis();
} /**
* 相互比较排序用,延迟队列队列头总是存储快要过期的数据
*/
@Override
public int compareTo(Delayed o) {
Wangming wangming = (Wangming) o;
return endTime - wangming.endTime > 0 ? 1 : -1;
} @Override
public String toString() {
return "Wangming [name=" + name + ", endTime=" + endTime + "]";
} public static void main(String[] args) {
DelayQueue<Wangming> queue = new DelayQueue<Wangming>();
Wangming man = new Wangming("a", 1000 * 11 + System.currentTimeMillis());
Wangming man1 = new Wangming("b", 1000 * 3 + System.currentTimeMillis());
Wangming man2 = new Wangming("c", 1000 * 2 + System.currentTimeMillis());
queue.add(man); queue.add(man1);
queue.add(man2);
try {
while (true) {
System.out.println(queue.take());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} }

  

下面简单说明下DelayQueue的原理

DelayQueue内部的实现使用了一个优先队列。当调用DelayQueue的offer方法时,把Delayed对象加入到优先队列q中。如下:

public boolean offer(E e) {
if (e == null)
throw new NullPointerException();
modCount++;
int i = size;
if (i >= queue.length) //长度不够扩容
grow(i + 1);
size = i + 1;
if (i == 0) //还没有元素 会直接加入
queue[0] = e;
else //有元素了,排序加入 加入顺序跟你的比较器有关
siftUp(i, e);
return true;
}

  关于take()方法

 public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
for (;;) {
E first = q.peek();
if (first == null)
available.await();
else {
long delay = first.getDelay(NANOSECONDS);
if (delay <= 0)
return q.poll();
first = null; // 防止内存泄漏
if (leader != null)
available.await();
else {
Thread thisThread = Thread.currentThread();
leader = thisThread;
try {
available.awaitNanos(delay);
} finally {
if (leader == thisThread)
leader = null;
}
}
}
}
} finally {
if (leader == null && q.peek() != null)
available.signal();
lock.unlock();
}
}

  基本流程比较简单 ,主要这里需要注意2点

   first  = null  //主要是为了防止内存泄漏
   leader  减少等待时间
   

java多线程系列11 juc包下的队列的更多相关文章

  1. java多线程系列 目录

    Java多线程系列1 线程创建以及状态切换    Java多线程系列2 线程常见方法介绍    Java多线程系列3 synchronized 关键词    Java多线程系列4 线程交互(wait和 ...

  2. Java多线程系列--“JUC锁”11之 Semaphore信号量的原理和示例

    概要 本章,我们对JUC包中的信号量Semaphore进行学习.内容包括:Semaphore简介Semaphore数据结构Semaphore源码分析(基于JDK1.7.0_40)Semaphore示例 ...

  3. Java多线程系列--“JUC锁”02之 互斥锁ReentrantLock

    本章对ReentrantLock包进行基本介绍,这一章主要对ReentrantLock进行概括性的介绍,内容包括:ReentrantLock介绍ReentrantLock函数列表ReentrantLo ...

  4. Java多线程系列--“JUC锁”03之 公平锁(一)

    概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...

  5. Java多线程系列--“JUC锁”01之 框架

    本章,我们介绍锁的架构:后面的章节将会对它们逐个进行分析介绍.目录如下:01. Java多线程系列--“JUC锁”01之 框架02. Java多线程系列--“JUC锁”02之 互斥锁Reentrant ...

  6. Java多线程系列--“JUC锁”06之 Condition条件

    概要 前面对JUC包中的锁的原理进行了介绍,本章会JUC中对与锁经常配合使用的Condition进行介绍,内容包括:Condition介绍Condition函数列表Condition示例转载请注明出处 ...

  7. Java多线程系列--“JUC锁”07之 LockSupport

    概述 本章介绍JUC(java.util.concurrent)包中的LockSupport.内容包括:LockSupport介绍LockSupport函数列表LockSupport参考代码(基于JD ...

  8. Java多线程系列--“JUC锁”08之 共享锁和ReentrantReadWriteLock

    概要 Java的JUC(java.util.concurrent)包中的锁包括"独占锁"和"共享锁".在“Java多线程系列--“JUC锁”02之 互斥锁Ree ...

  9. Java多线程系列--“JUC集合”04之 ConcurrentHashMap

    概要 本章是JUC系列的ConcurrentHashMap篇.内容包括:ConcurrentHashMap介绍ConcurrentHashMap原理和数据结构ConcurrentHashMap函数列表 ...

随机推荐

  1. 用到的linux命令

    1.修改文件权限 chmod 777 文件路径 修改文件下所有文件权限 chmond -R 777 文件路径 2.修改文件 (保存文件的方法,在命令行窗口 shift+:换出底部命令行, q表示退出, ...

  2. Emscripten 安装和使用

    OS: Windows 10 x64 I. install 0. pre install Python2.7 Node js Java 1. down git clone https://github ...

  3. 教你phpstudy如何搭建本地多站点

    经常做多个网站同时开发,如何才能在本地能使部署多个站点,今天就来分享一下如何用PHPstudy搭建本地多站点. 点击上图中的 其它选项菜单 ,就会弹出下面的对话框,然后点击 站点域名管理 然后在 网站 ...

  4. SpringMVC 启动流程

    首先看一下Web应用部署初始化过程 (Web Application Deployement),官方文档说明: Web Application Deployment When a web applic ...

  5. IntelliJ IDEA 常用设置

    1.idea每次打开项目的设置 2.设置编译器的快捷键  File->Keymap 在列表里面选择快捷键的名称  如果想使用跟Eclipse一样的快捷键,选中Eclipse copy即可 3.滚 ...

  6. hive 表锁和解锁

    场景: 在执行insert into或insert overwrite任务时,中途手动将程序停掉,会出现卡死情况(无法提交MapReduce),只能执行查询操作,而drop insert操作均不可操作 ...

  7. RestExpress response中addHeader 导致stackOverflow

    问题描述: 最近在项目使用中要在restExpress的header中增加一个键值对,同事在使用的时候没有对header的value进行非空判断,于是在测试环境测试的时候就出现了一个异常

  8. setTimeout应用例子-移入移出div显示和隐藏

    效果:移入div1,div2保持显示,移出div1,div2消失. 移入div2,div2保持显示,移出div2,div2消失. 一.HTML代码 <div id='div1'></ ...

  9. 使用List需要注意的点

    目录 1. 概述 2. Arrays.asList(); 2-1. 产生不可操作的集合 2-2. 需要传入对象数组而不是基本类型数组 3. arrayList.subList(); 3-1. subL ...

  10. 37.Spring-事务控制.md

    目录 1.分类 2.Spring对jadc事务管理 2.1xml方式 2.1.1首先定义Dao对象和Server对象 2.1.2配置文件实现事务管理 2.2注解方式 2.2.1对象类 2.2.2配置文 ...