阻塞队列
FIFO: first in put first out put 先进先出
阻塞队列:含义如上的图两种情况
BlockingQueue 不是新的东西
什么情况下我们会使用阻塞队列:多线程并发处理,线程池!
IDEA 类关系图:
学会使用队列
这里面就两个操作:添加,移除
*四组Api
方式 | 抛出异常 | 有返回值,不抛出异常 | 阻塞 等待 | 超时等待 |
---|---|---|---|---|
添加 | add | offer() | put() | offer( ,,) |
移除 | remove | poll () | take() | poll( ,) |
判断队列的首部 | element | peek |
- 抛出异常
- 不会抛出异常
- 阻塞等待
- 超时等待
四种情况代码案例:
package com.bq;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
public class Test {
public static void main(String[] args) throws InterruptedException {
//Collection
//List
//Set
//BlockingQueue 不是新的东西
//Test.test1();
//Test.test2();
//Test.test3();
Test.test4();
}
/**
* 第一组api 抛出异常
*/
public static void test1(){
//入参:默认的队列大小为3
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.element());
System.out.println("======================================");
//我想再添加一个元素,结果抛出异常 java.lang.IllegalStateException: Queue full
// System.out.println(blockingQueue.add("d"));
//先进先出,正常弹出,移除元素 a
System.out.println(blockingQueue.remove());
//移除a 后在检测队首是哪个元素
System.out.println(blockingQueue.element());
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
//已经是空的,如果我再取数据,也会抛出异常 java.util.NoSuchElementException
// System.out.println(blockingQueue.remove());
}
/**
*
* 有返回值,没有异常
*/
public static void test2(){
//入参默认队列的大小为3,这种不抛出异常的用offer 方法
ArrayBlockingQueue<Object> 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.peek());
//因为默认初始化大小3,所有在假如第4个值得时候,不像上面add 方法一样抛出异常,现在返回为 false!
System.out.println(blockingQueue.offer("d"));
System.out.println("===================================================");
//将所有的数据弹出来
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
//这个是返回null 不抛出异常了!
System.out.println(blockingQueue.poll());
}
/**
*
* 等待,阻塞(一直阻塞)
*/
public static void test3() throws InterruptedException {
//入参默认队列的大小为3,这种一直阻塞的就用put 方法
ArrayBlockingQueue<Object> blockingQueue = new ArrayBlockingQueue<>(3);
//put 方法是没有返回值的
blockingQueue.put("a");
blockingQueue.put("b");
blockingQueue.put("c");
//队列没有位置了,添加d 元素会处于一直等待状态
//blockingQueue.put("d");
//取值
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
//上面已经取出3个元素了,如果我再取一次会出现什么了
//如果这么操作则一直会等待这个操作,代码就死在这个地方了,一直阻塞!
System.out.println(blockingQueue.take());
}
/**
*
* 等待,阻塞(等待超时)
*/
public static void test4() throws InterruptedException {
//队列的大小
ArrayBlockingQueue<Object> blockingQueue = new ArrayBlockingQueue<>(3);
blockingQueue.offer("a");
blockingQueue.offer("b");
blockingQueue.offer("c");
//假设再增加(d元素,超时时间,超时时间单位)
//等待2 s 要时还是没有位置让我插入,等待超过2s 就退出!
blockingQueue.offer("d",2,TimeUnit.SECONDS);
System.out.println("==============");
//取出值了
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
//等待超过2 秒就退出
blockingQueue.poll(2,TimeUnit.SECONDS);
}
}
同步队列SynchronousQueue
没有容量
进去一个元素,必须等待取出来知乎,才能再往里面放一个元素!
put,take
package com.bq;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
/**
* 同步队列
* 与其他的BlockQueue 不一样,SynchronousQueue 不存储元素
* 只要在里面put 一个元素,必须从里面take 取出来,否则不能在put 进去值!
*/
public class SynchronousQueueDemo {
public static void main(String[] args) {
BlockingQueue<String> blockingQueue = new SynchronousQueue<String>();
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();
}
}
输出结果:
T1=put 1
T2=>1
T1=put 2
T2=>2
T1=put 3
T2=>3