9.阻塞队列和同步队列
感谢秦疆老师的JUC并发编程视频,更多了解哔哩哔哩搜索【狂神说Java】。
本文内容源于秦疆老师的JUC并发编程视频教程。给狂神推荐,点赞吧!
阻塞队列
阻塞 队列
当阻塞队列为空时,从队列中获取元素的操作将会被阻塞。
当阻塞队列为满时,从队列里添加元素的操作将会被阻塞。
BlockingQueue
BlockingQueue 不是新的东西
什么情况下我们会使用队列?
多线程并发处理,线程池!
学会使用队列
添加、移除
四组API
方式 | 抛出异常 | 有返回值,不抛出异常 | 阻塞等待 | 超时等待 |
---|---|---|---|---|
添加 | boolean add(E e) | boolean offer(E e) | void put(E e) | boolean offer(E e, long timeout, TimeUnit unit) |
移除 | E remove() | E poll() | E take() | E poll(long timeout, TimeUnit unit) |
检测队首元素 | E element() | E peek() | / | / |
代码测试:
package bq;
import java.sql.Time;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
public class BlockingQueueTest {
public static void main(String[] args) {
try {
//test3();
test4();
} catch (InterruptedException e) {
e.printStackTrace();
}
// test2();
// test1();
}
}
- 抛出异常
/**
* 抛出异常
*/
public static void test1(){
//队列的大小
ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue<>(3);
System.out.println(arrayBlockingQueue.add("队列a"));
System.out.println(arrayBlockingQueue.add("队列b"));
System.out.println(arrayBlockingQueue.add("队列c"));
//java.lang.IllegalStateException: Queue full
//System.out.println(arrayBlockingQueue.add("队列d"));
System.out.println("=================查看对首元素===============");
System.out.println(arrayBlockingQueue.element());
System.out.println("=================移除===============");
System.out.println(arrayBlockingQueue.remove());
System.out.println(arrayBlockingQueue.remove());
System.out.println(arrayBlockingQueue.remove());
//java.util.NoSuchElementException
// System.out.println(arrayBlockingQueue.remove());
}
输出:
true
true
true
=================查看对首元素===============
队列a
=================移除===============
队列a
队列b
队列c
- 有返回值,没有异常
/**
* 有返回值,不抛出异常
*/
public static void test2(){
//队列的大小
ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue<>(3);
System.out.println(arrayBlockingQueue.offer("队列a"));
System.out.println(arrayBlockingQueue.offer("队列b"));
System.out.println(arrayBlockingQueue.offer("队列c"));
//返回Boolean值 false 不抛出异常
System.out.println(arrayBlockingQueue.offer("队列d"));
System.out.println("=================查看对首元素===============");
System.out.println(arrayBlockingQueue.peek());
System.out.println("=================移除===============");
System.out.println(arrayBlockingQueue.poll());
System.out.println(arrayBlockingQueue.poll());
System.out.println(arrayBlockingQueue.poll());
//返回 null
System.out.println(arrayBlockingQueue.poll());
}
输出:
true
true
true
false
=================查看对首元素===============
队列a
=================移除===============
队列a
队列b
队列c
null
- 等待,阻塞(一直阻塞)
/**
* 等待,阻塞(一直阻塞)
*/
public static void test3() throws InterruptedException {
//队列的大小
ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue<>(3);
//一直阻塞
arrayBlockingQueue.put("队列a");
arrayBlockingQueue.put("队列b");
arrayBlockingQueue.put("队列c");
//队列没有位置了,一直阻塞
//arrayBlockingQueue.put("队列d");
System.out.println("=================移除===============");
System.out.println(arrayBlockingQueue.take());
System.out.println(arrayBlockingQueue.take());
System.out.println(arrayBlockingQueue.take());
//没有这个元素 也会一直阻塞
//System.out.println(arrayBlockingQueue.take());
System.out.println("测试是否等待!");
}
输出:
=================移除===============
队列a
队列b
队列c
测试是否等待!
- 等待,阻塞(超时等待)
/**
* 等待,阻塞(等待超时)
*/
public static void test4() throws InterruptedException {
//队列的大小
ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue<>(3);
arrayBlockingQueue.offer("队列a");
arrayBlockingQueue.offer("队列b");
arrayBlockingQueue.offer("队列c");
//等待超过两秒就退出
arrayBlockingQueue.offer("队列d", 2, TimeUnit.SECONDS);
System.out.println("超时等待两秒后输出!");
System.out.println("=================移除===============");
arrayBlockingQueue.poll();
arrayBlockingQueue.poll();
arrayBlockingQueue.poll();
//等待超过两秒就退出
arrayBlockingQueue.poll(2, TimeUnit.SECONDS);
System.out.println("超时等待两秒后输出!");
}
输出:
超时等待两秒后输出!
=================移除===============
超时等待两秒后输出!
同步队列 (SynchronousQueue)
没有容量, 进去一个元素,必须等待取出来之后,才能再往里面放一个元素!
put、take
代码测试:
package bq;
import com.sun.org.apache.bcel.internal.generic.NEW;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
/**
* 同步队列
* 和其他的BlockingQueue不一样,SynchronousQueue不存储元素
* put了一个元素,必须从里面先take取出来,否则不能再在put进去值!
*/
public class SynchronousQueueTest {
public static void main(String[] args) {
//同步队列SynchronousQueue
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 (Exception e) {
e.printStackTrace();
}
}, "线程A").start();
new Thread(() -> {
try {
//睡3秒
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 (Exception e) {
e.printStackTrace();
}
}, "线程B").start();
}
}
输出:
线程A: put 1
线程B=>1
线程A: put 2
线程B=>2
线程A: put 3
线程B=>3