BlockingQueue
阻塞队列:在多线程领域:在某些情况下会挂起线程(即阻塞),一旦条件满足,被挂起的线程又会自动被唤起;BlockingQueue 很好的解决了多线程中,如何高效安全 “传输”数据的问题
常用的队列:
先进先出(FIFO):先插入的队列的元素也最先出队列,类似于排队的功能。从某种程度上来说这种队列也体现了一种公平性
后进先出(LIFO):后插入队列的元素最先出队列,这种队列优先处理最近发生的事件(栈)
优势:
不需要关心什么时候需要阻塞线程,什么时候需要唤醒线程;
核心方法:
方式 | 抛出异常 | 不会抛出异常(有返回值) | 阻塞 等待 | 超时等待 |
添加 | add() | offer() | put() | offer() |
移出 | remove() | poll() | task() | poll() |
判断队列首 | element() | peek() | - | - |
1.抛出异常
public static void test1(){
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue(3);
System.out.println(blockingQueue.add("1"));
System.out.println(blockingQueue.add("2"));
System.out.println(blockingQueue.add("3"));
System.out.println(blockingQueue.element());
//抛出异常Queue full 队列已满
//System.out.println(blockingQueue.add("4"));
System.out.println("======!======");
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
//抛出异常java.util.NoSuchElementException
//System.out.println(blockingQueue.remove());
}
2.不抛出异常
public static void test2(){
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue(3);
System.out.println(blockingQueue.offer("1"));
System.out.println(blockingQueue.offer("2"));
System.out.println(blockingQueue.offer("3"));
//System.out.println(blockingQueue.offer("4")); //不抛出异常 false
System.out.println(blockingQueue.peek());
System.out.println("======!======");
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
//System.out.println(blockingQueue.poll()); //不抛出异常 null
}
3. 堵塞 一直等待
public static void test3() throws InterruptedException{
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue(3);
blockingQueue.put("1");
blockingQueue.put("2");
blockingQueue.put("3");
//blockingQueue.put("4"); //队列没有位置,一直堵塞
System.out.println("======!======");
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
//System.out.println(blockingQueue.take()); //没有这个元素一直堵塞
}
4.堵塞 等待超时
public static void test4() throws InterruptedException{
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue(3);
System.out.println(blockingQueue.offer("1"));
System.out.println(blockingQueue.offer("2"));
System.out.println(blockingQueue.offer("3"));
System.out.println(blockingQueue.offer("4",2, TimeUnit.SECONDS)); //超过等待2秒退出
System.out.println("======!======");
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll(2, TimeUnit.SECONDS)); //超过等待2秒退出
}
SynchronousQueue
同步队列
真正意义上来说并不能算是一个队列,而将其理解为一个用于线程之间通信的组件更为恰当。没有容量 进去一个 元素,必须等待取出来之后 才能继续添加元素
/*
* 同步队列
* 和其他的BlockingQueue不一样 SynchronousQueue 不存储元素
* put了一个元素 必须从里面take取出来 否则不能再put进去元素
*
* */
public class SynchronousQueueDemo {
public static void main(String[] args) {
SynchronousQueue synchronousQueue = new SynchronousQueue();
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + "put1");
synchronousQueue.put("1");
System.out.println(Thread.currentThread().getName() + "put2");
synchronousQueue.put("2");
System.out.println(Thread.currentThread().getName() + "put3");
synchronousQueue.put("3");
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "T1").start();
new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(3);
System.out.println(synchronousQueue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(synchronousQueue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(synchronousQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "T2").start();
}
}