LinkedBlockingQueue
LinkedBlockingQueue
是java.util.concurrent
包下的新类。LinkedBlockingQueue就是其中之一,是一个阻塞的线程安全的队列,底层采用链表实现。
LinkedBlockingQueue构造的时候若没有指定大小,则默认大小为Integer.MAX_VALUE,当然也可以在构造函数的参数中指定大小。LinkedBlockingQueue不接受null。
添加元素的方法有三个:add
,put
,offer
,且这三个元素都是向队列尾部添加元素的意思。
区别:
- add方法在添加元素的时候,若超出了度列的长度会直接抛出异常:
- put方法,若向队尾添加元素的时候发现队列已经满了会发生阻塞一直等待空间,以加入元素。
- offer方法在添加元素时,如果发现队列已满无法添加的话,会直接返回false。
从队列中取出并移除头元素的方法有:poll
,remove
,take
。
- poll: 若队列为空,返回null。
- remove:若队列为空,抛出NoSuchElementException异常。
- take:若队列为空,发生阻塞,等待有元素。
线程安全例子,直接上代码吧。
package com.system.net.queue;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
public class LinkedBlockingQueueTest {
public static void main(String[] args) throws InterruptedException {
final Queue<Integer> q1 = new LinkedBlockingQueue<Integer>();
final Queue<Integer> q2 = new LinkedBlockingQueue<Integer>();
final int n = 1000000;
final int m = 100;
for (int i = 0; i < n; i++) {
q1.add(i);
}
List<Thread> ts = new ArrayList<Thread>();
for (int i = 0; i < m; i++) {
ts.add(new Thread(new Runnable() {
public void run() {
int i = 0;
while (q2.size() < n && i++ < n / m) { // q2.size() 非线程安全,所以设置每个线程添加平均个数,防止poll出null报错
q2.add(q1.poll());
}
}
}));
}
for (Thread t : ts) {
t.start();
}
System.out.println("启动了 " + m + " 个线程,每个线程处理 " + n / m + " 个操作");
for (Thread t : ts) {
while (t.isAlive()) {
Thread.sleep(1);
}
}
System.out.println("q1.size():" + q1.size());
System.out.println("q2.size():" + q2.size());
Set<Integer> set = new HashSet<Integer>();
Integer i;
while ((i = q2.poll()) != null) {
set.add(i);
}
System.out.println("q2.size():" + q2.size());
System.out.println("set.size():" + set.size());
}
}