BlockingQueue作为阻塞队列,是一个接口,也是Queue的子接口。BlockingQueue具有一个特征:当生产者线程试图向BlockingQueue中放入元素时,如果该队列已满,则该线程被阻塞;当消费者线程试图从BlockingQueue中取出元素时,如果队列已空,则该线程阻塞。
线程间通信:程序的两个线程通过交替向BlockingQueue中放入元素、取出元素,即可很好地控制线程通信。
BlockingQueue提供如下两个支持阻塞的方法:
put(E e):尝试把元素放入BlockingQueue的尾部,如果该队列已满,则阻塞该线程;
take():尝试从BlockingQueue的头部取出元素,如果该队列的元素已空,则阻塞该线程。
BlockingQueue继承了Queue接口,当然也可以使用Queue接口中的方法,这些方法归纳起来可以分为如下三组:
1.在队列尾部插入元素,包括add(E e)、offer(E e)、put(E e),当队列已满时,这三个方法分别会抛出异常、返回false、阻塞线程;
2.在队列头部删除并返回删除的元素,包括remove()、poll()、take(),当队列已空时,这三个方法分别会抛出异常、返回false、阻塞线程;
3.在队列头部取出但不删除元素,包括element()和peek()方法,当队列已空时,这两个方法分别会抛出异常、返回false。
代码举例:
class Producer extends Thread {//生产者
private BlockingQueue<String> queue;
public Producer(BlockingQueue<String> queue) {
this.queue = queue;
}
public synchronized void run() {
String[] strs = {"a", "b", "c", "d"};
for(String str : strs) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
queue.put(str);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("producer size: "+queue.size());
}
}
}
class Consumer extends Thread {//消费者
private BlockingQueue<String> queue;
public Consumer(BlockingQueue<String> queue) {
this.queue = queue;
}
public synchronized void run() {
while(true) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
queue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("consumer size: "+queue.size());
}
}
}
//测试代码
BlockingQueue<String> queue = new ArrayBlockingQueue<String>(3);
Producer p = new Producer(queue);
Consumer c =new Consumer(queue);
p.start();
c.start();
转载于:https://www.cnblogs.com/yuanfei1110111/p/10144459.html