一、阻塞队列
1、什么是阻塞队列
阻塞队列,它是一个队列,满足FIFO
- 当阻塞队列为空时,从队列中获取元素的操作将会被阻塞
- 当阻塞队列是满的时候,往队列添加元素的操作将会被阻塞
2、阻塞队列有哪些
阻塞队列有七种,但是常用的只有三种,使用LinkedBlockingQueue需要注意的是创建的时候要设置大小,否则默认是Integer.MAX_VALUE
3、为什么要使用阻塞队列
在多线程的领域,所谓阻塞就是在某些情况下会挂起的线程,一旦条件满足,被挂起的线程又会被重新唤醒。
在过去,多线程环境下,需要程序员自己编码控制这些细节。但现在有了阻塞队列之后,阻塞线程,唤醒线程全都交给BlockQueue去完成,不用我们去担心了
二、阻塞队列的核心方法
方法类型 | 抛出异常 | 特殊值 | 阻塞 | 超时 |
---|---|---|---|---|
插入 | add(e) | offer(e) | put(e) | offer(e,time,unit) |
移除 | remove() | poll() | take() | poll(time, unit) |
检查 | element() | peek() | 不可用 | 不可用 |
-
抛出异常
1、当阻塞队列满时,再往队列里插入元素会抛出IllegalStateException:Queue full
2、当阻塞队列为空时,再从队列里移除元素会抛出NoSuchElementException -
特殊值
1、插入方法,成功返回true,失败返回false(一般来说队列满了再插入就会返回false)
2、移除方法,成功则返回队列的元素,队列里面没有就返回null -
阻塞
1、当阻塞队列满时,生产者线程继续往队列里put元素,队列会一直阻塞生产者线程直到put数据成功或者响应中断
2、当阻塞队列为空时,消费者线程还尝试从队列里take元素,队列会一直阻塞消费者线程,直到队列可用 -
超时
1、当阻塞队列满时,生产者线程继续往队列里put元素,队列会阻塞生产者线程一段时间,超过时间限制后,生产者线程退出
2、当阻塞队列空时,消费者线程还尝试从队列里take元素,队列会阻塞消费者线程一段时间,超过时间限制后,消费者线程退出
以ArrayBolckQueue来验证上述四组API的调用
1、抛出异常
/**
* 测试阻塞队列四组API
*/
public class Test {
public static void main(String[] args) throws InterruptedException {
test1();
}
public static void test1(){
/**
* 抛出异常
*/
ArrayBlockingQueue blockingQueue=new ArrayBlockingQueue(3);
System.out.println(blockingQueue.add("a"));
System.out.println(blockingQueue.add("b"));
System.out.println(blockingQueue.add("c"));
System.out.println(blockingQueue.add("d"));
blockingQueue.remove();
blockingQueue.remove();
blockingQueue.remove();
blockingQueue.remove();
}
}
2、特殊值
public class Test {
public static void main(String[] args) throws InterruptedException {
test2();
}
public static void test2(){
/**
* 不抛异常
*/
ArrayBlockingQueue blockingQueue=new ArrayBlockingQueue(3);
System.out.println(blockingQueue.offer("a"));
System.out.println(blockingQueue.offer("b"));
System.out.println(blockingQueue.offer("c"));
System.out.println(blockingQueue.offer("d"));
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
}
}
3、阻塞
public class Test {
public static void main(String[] args) throws InterruptedException {
test3();
}
public static void test3() throws InterruptedException {
/**
* 一直阻塞
*/
ArrayBlockingQueue blockingQueue=new ArrayBlockingQueue(3);
blockingQueue.put("a");
blockingQueue.put("b");
blockingQueue.put("c");
blockingQueue.put("d");
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
}
}
4、超时
public class Test {
public static void main(String[] args) throws InterruptedException {
test4();
}
public static void test4() throws InterruptedException {
/**
* 超时等待
*/
ArrayBlockingQueue blockingQueue=new ArrayBlockingQueue(3);
System.out.println(blockingQueue.offer("a",2, TimeUnit.SECONDS));
System.out.println(blockingQueue.offer("b"));
System.out.println(blockingQueue.offer("c"));
System.out.println(blockingQueue.offer("d",2,TimeUnit.SECONDS));
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
}
}
三、 synchronousQueue
这个队列比较特殊,所以单独把它拿出来讲解
SynchronousQueue没有容量,每一个put操作必须要等待一个take操作,否则不能继续添加元素,反之亦然
public class SynchronousQueueDemo {
public static void main(String[] args) {
//同步队列
BlockingQueue<String> blockingQueue=new SynchronousQueue<>();
new Thread(()->{
try {
System.out.println(Thread.currentThread().getName()+"put 1");
blockingQueue.put("1");
System.out.println(Thread.currentThread().getName()+"put 2");
blockingQueue.put("2");
System.out.println(Thread.currentThread().getName()+"put 3");
blockingQueue.put("3");
} catch (InterruptedException e) {
e.printStackTrace();
}
},"T1").start();
new Thread(()->{
try {
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()+"==>"+blockingQueue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()+"==>"+blockingQueue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()+"==>"+blockingQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
},"T2").start();
}
}