阻塞式集合:这类集合包括添加和移除数据的方法。当集合已满或者为空时,被调用的添加或者移除方法不能立即被执行,那么调用这个方法的线程被阻塞,一直到该方法可以被成功执行。如LinkedBlockingDeque\PriorityBlockingQueue
非阻塞式集合:这类集合也包括添加和移除数据的方法。如果方法不能立即被执行,则返回null或抛出异常,但调用这个方法的线程不会被阻塞。如ConcurentLinkedDeque\DelayQueue
ConcurrentLinkedDeque/LinkedBlockingDeque
package mytest;
import java.util.concurrent.ConcurrentLinkedDeque;
/**
* ConcurentLinkedDeque: 线程安全的、非阻塞式的、双端、无界队列<br>
*
* peek()/peekFirst()/peekLast:返回列表中第一个或最后一个,返回的元素不会从列表中移除,如果列表为空,则返回null
* getFirst/getLast:返回列表中第一个或最后一个,返回的元素不会从列表中移除,如果列表为空,则抛出NoSuchElementException
*
* pollFist/pollLast:移除元素,如果列表为空,则返回null
* removeFirst/removeLast/remove:移除元素,如果列表为空,则抛出NoSuchElementException
*
*/
public class ConcurentLinkedDequeTest {
private static ConcurrentLinkedDeque<Integer> cld = new ConcurrentLinkedDeque<Integer>();
//可以指定队列大小,不指定时,为Integer.MAX_VALUE.Blocking意味着会有阻塞机制
private static LinkedBlockingDeque<Integer> lbd = new LinkedBlockingDeque<Integer>();
static class AddTask implements Runnable {
public void run() {
for (int i = 0; i < 1000; i++) {
cld.add(i);
}
}
}
static class PollTask implements Runnable {
public void run() {
for (int i = 0; i < 500; i++) {
cld.pollFirst();
cld.pollLast();
cld.pollLast();
}
}
}
public static void main(String[] args) {
// 创建添加线程任务
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.length; i++) {
Thread at = new Thread(new AddTask());
threads[i] = at;
threads[i].start();
}
System.out.println("add task threads have been lauched.count:" + threads.length);
for (int i = 0; i < threads.length; i++) {
try {
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("size of list :" + cld.size());
for (int i = 0; i < threads.length; i++) {
Thread at = new Thread(new PollTask());
threads[i] = at;
threads[i].start();
}
System.out.println("poll task threads have been lauched.count:" + threads.length);
for (int i = 0; i < threads.length; i++) {
try {
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("size of list :" + cld.size());
}
}
输出
add task threads have been lauched.count:10
size of list :10000
poll task threads have been lauched.count:10
size of list :0
PriorityBlockingQueue
package mytest;
import java.util.concurrent.PriorityBlockingQueue;
//有序组合队列
//当插入元素时,PriorityBlockingQueue使用compareTo方法来决定插入元素的位置,元素越大越靠后
public class PriorityBlockingQueueTest {
static class Event implements Comparable<Event> {
private int thread;
private int priority;
public Event(int thread, int priority) {
this.thread = thread;
this.priority = priority;
}
public int getThread() {
return thread;
}
public int getPriority() {
return priority;
}
@Override
public int compareTo(Event o) {
if (this.priority > o.getPriority()) {
return -1;
} else if (this.priority < o.getPriority()) {
return 1;
}
return 0;
}
}
static class Task implements Runnable {
private int id;
private PriorityBlockingQueue queue;
public Task(int id, PriorityBlockingQueue<Event> queue) {
this.id = id;
this.queue = queue;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
Event event = new Event(id, i);
queue.add(event);
}
}
}
public static void main(String[] args) {
PriorityBlockingQueue<Event> queue = new PriorityBlockingQueue<Event>();
Thread taskThread[] = new Thread[5];
for (int i = 0; i < taskThread.length; i++) {
Task task = new Task(i, queue);
taskThread[i] = new Thread(task);
}
for (int i = 0; i < taskThread.length; i++) {
taskThread[i].start();
}
for (int i = 0; i < taskThread.length; i++) {
try {
taskThread[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int i = 0; i < taskThread.length * 100; i++) {
Event poll = queue.poll();
System.out.println("thread :" + poll.getThread() + ";priority:" + poll.getPriority());
}
}
}
输出结果
thread :1;priority:99
thread :4;priority:99
thread :2;priority:99
thread :0;priority:99
thread :3;priority:99
thread :1;priority:98
thread :4;priority:98
thread :2;priority:98
thread :0;priority:98
thread :3;priority:98
DelayQueue
package mytest;
import java.util.Date;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.TimeUnit;
//DelayQueue中的元素必须继承Delayed接口。该接口使对象成为延迟对象,它使放在DelayQueue中的对象具有激活日期
//未到期的元素你是获取不到嘀
public class DelayQueueTest {
static class Event implements Delayed {
private Date startDate;
public Event(Date startDate) {
this.startDate = startDate;
}
@Override
public int compareTo(Delayed o) {
// 将毫秒转换成纳秒进行比较
long result = this.getDelay(TimeUnit.NANOSECONDS) - o.getDelay(TimeUnit.NANOSECONDS);
if (result < 0) {
return -1;
} else if (result > 0) {
return 1;
}
return 0;
}
@Override
public long getDelay(TimeUnit unit) {
Date now = new Date();
long diff = startDate.getTime() - now.getTime();
return unit.convert(diff, TimeUnit.MILLISECONDS);// 激活日期到当前日期的毫秒数;diff和第二个参数类型一致
}
}
static class Task implements Runnable {
private int id;
private DelayQueue queue;
public Task(int id, DelayQueue<Event> queue) {
this.id = id;
this.queue = queue;
}
@Override
public void run() {
Date now = new Date();
Date delay = new Date();
delay.setTime(now.getTime() + (id * 5000));
System.out.println("Thread id:" + id + ";delay:" + delay);
for (int i = 0; i < 100; i++) {
Event event = new Event(delay);
queue.add(event);
}
}
}
public static void main(String[] args) throws InterruptedException {
Date now = new Date();
long minutes = TimeUnit.HOURS.toMinutes(1);
System.out.println(minutes);
System.out.println(TimeUnit.NANOSECONDS.convert(1000L, TimeUnit.MILLISECONDS));
DelayQueue<Event> queue = new DelayQueue<Event>();
Thread taskThread[] = new Thread[5];
for (int i = 0; i < taskThread.length; i++) {
Task task = new Task(i + 1, queue);
taskThread[i] = new Thread(task);
}
for (int i = 0; i < taskThread.length; i++) {
taskThread[i].start();
}
for (int i = 0; i < taskThread.length; i++) {
try {
taskThread[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
do {
int counter = 0;
Event event;
do {
// 只取已经到了激活时间的event
event = queue.poll();
if (event != null)
counter++;
} while (event != null);
System.out.println("At " + new Date() + " you have read " + counter + " events");
TimeUnit.SECONDS.sleep(1);//休息1秒尝试取一次
} while (queue.size() > 0);// 一直等到将队列取光
}
}
结果:可见5秒钟激活一组数据
At Tue Mar 21 15:48:32 CST 2017 you have read 0 events
At Tue Mar 21 15:48:33 CST 2017 you have read 0 events
At Tue Mar 21 15:48:34 CST 2017 you have read 0 events
At Tue Mar 21 15:48:35 CST 2017 you have read 0 events
At Tue Mar 21 15:48:36 CST 2017 you have read 0 events
At Tue Mar 21 15:48:37 CST 2017 you have read 100 events
At Tue Mar 21 15:48:38 CST 2017 you have read 0 events
At Tue Mar 21 15:48:39 CST 2017 you have read 0 events
At Tue Mar 21 15:48:40 CST 2017 you have read 0 events
At Tue Mar 21 15:48:41 CST 2017 you have read 0 events
At Tue Mar 21 15:48:42 CST 2017 you have read 100 events