Queue
在并发队列上JDK提供2套实现,一个是以ConcurrentLinkedQueue为代表的高性能队列,一个是以BlockingQueue接口为代表的阻塞队列,一个是以BlockingQueue接口为代表的阻塞队列,无论哪种都继承自Queue接口。
boolean add(E e)
将指定的元素插入此队列(如果立即可行且不会违反容量限制),在成功时返回 true,如果当前没有可用的空间,则抛出 IllegalStateException。boolean offer(E e)
将指定的元素插入此队列(如果立即可行且不会违反容量限制),当使用有容量限制的队列时,此方法通常要优于add(E)
,后者可能无法插入元素,而只是抛出一个异常。remove()
获取并移除此队列的头。此方法与poll
唯一的不同在于:此队列为空时将抛出一个异常。
poll()
获取并移除此队列的头,如果此队列为空,则返回 null。
peek()
获取但不移除此队列的头;如果此队列为空,则返回 null。
ConcurrentLinkedQueue类
是一个适用于高并发产经下的队列,通过无锁的方式,实现了高并发状态下的高性能,通常ConcurrentLinkedQueue性能好于BlockingQueue。他是一个机遇链接点的无界线程安全队列。
该队列是先进先出的原则,头是最先加入的,尾是最近加入的。该队列不允许NULL元素;
add()和offer()都是加入元素,ConcurrentLinkedQueue中这两个方法都没有任何的区别;
poll()和peek()都是取头元素节点,区别在于前者会删除元素,后者不会;
BlockingQueue接口
offer() 表示如果可能的话,将anObject加到BlockingQueuue里,即如果BlockingQueue可以容纳,则返回true,否者返回false.(本方法不阻塞当前执行的方法的线程)
offer(E O ,Long timeout,TimeUnit unit) 可以设定等待时间如果在指点的时间内还不能在队列之加入元素,则返回失败。
put(anObject) 把anObject加到BloclingQueue里,如果BlockQueue没有空间则调用此方法的线程被阻断直到BlockingQueue里面有空间再继续。
poll(long timeout,TimeUnit unit):从BlockingQueue取出一个队首的对象,如果在指定的时间内,队列一旦有数据可以取了则立即返回队列中的数据,否则知道时间超时还没有数据可以取的,返回失败。
take():取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态的BlockingQueue有新的数据被加入。
drainTo():一次性从BlockingQueue获取所有可用的数据对象(还可以指定获取数据的个数),通过该方法,可以提升获取数据效率;不需要多次分批加锁或释放锁。
实现类
ArrayBlockingQueue, DelayQueue, LinkedBlockingDeque, LinkedBlockingQueue,
MyQueue
package com.infree.thread.core.collection;
import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicInteger;
public class MyQueue {
private final LinkedList<Object> linkedList = new LinkedList<>();
private final AtomicInteger count = new AtomicInteger(0);
private final int maxSize;
private final int minSize = 0;
private final Object lock = new Object();
public MyQueue(int len) {
this.maxSize = len;
}
public void put(Object obj){
synchronized (lock) {
while(count.get() == this.maxSize){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 添加新的元素到容器中
linkedList.add(obj);
count.getAndIncrement(); //i++
lock.notify(); //唤醒线程
}
}
public Object take(){
Object item = null;
synchronized (lock) {
while(count.get()== this.minSize){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
item = linkedList.removeFirst();
count.getAndDecrement(); // i --
lock.notify();//唤醒线程
}
return item;
}
public int size() {
return linkedList.size();
}
public String getLinkListString() {
return linkedList.toString();
}
}
package com.infree.thread.core.collection;
public class MyQueueTest {
public static void main(String[] args) throws InterruptedException {
MyQueue myQueue = new MyQueue(5);
myQueue.put("a");
myQueue.put("b");
myQueue.put("c");
myQueue.put("d");
myQueue.put("e");
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
myQueue.put("f");
myQueue.put("g");
}
},"线程一");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
myQueue.take();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
myQueue.take();
}
},"线程2");
thread1.start();
Thread.sleep(1000);
System.err.println(myQueue.size());
thread2.start();
Thread.sleep(5000);
System.err.println(myQueue.getLinkListString());
}
}
附加:Arraylist和Linkedlist的区别