插入方法
- boolean add(E e);把E加到BlockingQueue里,如果可以容纳则返回true,否则抛出异常。
- boolean offer(E e);把E加到BlockingQueue里,如果可以容纳则返回true,否则返回false。
- void put(E e) throws InterruptedException;把E加到BlockingQueue里,如果没有空间,则调用此方法的线程被阻断直到BlockingQueue里面有空间再继续。
读取
- E poll(time);取走BlockingQueue里排在首位的对象,若不能立即取出,可以等到参数规定的时间,取不到时候返回null。
- take()取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态,直到有新的对象被加入。
其他
- int remainingCapacity();返回队列剩余容量,在队列插入或获取时可能数据不准。
- boolean remove(Object o);从队列移除元素,如果存在则移除一个或更多,队列改变了返回true。
- public boolean contains(Object o);查看队列里是否存在这个元素,存在返回true。
- int drainTo(Collection<? super E> c);移除此队列中所有可用的元素,并把他们添加到指定的collection中。
- int drainTo(Collection<? super E> c, int maxElements);和上面方法一样,指定了移动的数量。
具体实现类
- ArrayBlockingQueue:一个由数组支持的有界阻塞队列,规定大小的BlockingQueue,其构造函数必须带一个int参数来指明其大小,其所含的对象是以先入先出顺序排序的。
- LinkedBlockingQueue:大小不定的BlockingQueue,若其构造函数带一个规定大小的参数生成的BlockingQueue。有大小限制,若不带大小参数,所生成的BlockingQueue的大小由Integer.MAX_VALUE来决定,其所含的对象是以先入先出顺序排序的。
LinkedBlockingQueue可指定容量,也可以不指定,不指定的话,默认最大是Integer.MAX_VALUE,其中主要用到put和take方法,put方法在队列满的时候会阻塞直到有队列成员被消费,take方法在队列为空的时候会被阻塞,直到队列成员被放进来。
区别:他们背后所用的数据结构不一样,导致LinkedBlockingQueue的数据吞吐量要大于ArrayBlockingQueue,但在线程数量很大时其性能可预见性低于ArrayBlockingQueue.
例子
Producer
package org.shareing.myBlockingQueue;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
public class Producer implements Runnable {
BlockingQueue<String> queue;
public Producer(BlockingQueue<String> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
Thread.sleep(new Random().nextInt(10));
System.out.println("I have made a product:"+Thread.currentThread().getName());
String temp="A Product,生产线程,"+Thread.currentThread().getName();
queue.put(temp);
}catch (Exception e){
e.printStackTrace();
}
}
}
Consumer
package org.shareing.myBlockingQueue;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
public class Consumer implements Runnable {
BlockingQueue<String> queue;
public Consumer(BlockingQueue<String> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
Thread.sleep(new Random().nextInt(10));
String name = Thread.currentThread().getName();
System.out.println(name);
//如果队列为空会阻塞当前线程
String take = queue.take();
System.out.println(name+"进行消费"+take);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Test
package org.shareing.myBlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
public class Test {
public static void main(String[] args) {
LinkedBlockingDeque<String> queue = new LinkedBlockingDeque<>(2);
Consumer consumer = new Consumer(queue);
Producer producer = new Producer(queue);
for (int i = 0; i < 3; i++) {
new Thread(producer,"Producer"+(i+1)).start();
}
for (int i = 0; i < 5; i++) {
new Thread(consumer,"Consumer"+(i+1)).start();
}
}
}
运行结果:
Consumer1
I have made a product:Producer1
I have made a product:Producer3
Consumer1进行消费A Product,生产线程,Producer1
Consumer3
I have made a product:Producer2
Consumer3进行消费A Product,生产线程,Producer3
Consumer5
Consumer2
Consumer5进行消费A Product,生产线程,Producer2
Consumer4