阻塞对队列:
1.当线程需要去队列取值时,如果此时队列为空,则该线程会阻塞等待,直到有别的线程往该队列中加入值。
2.如果一个线程要往队列中加入值的时候,而此时队列已经满了,则该线程会一直等待下去,直到有一个线程把该队列的值取出来为止。
实现代码:
public class MyQueueTest {
/** 底层LinkedList去存储 */
private final LinkedList<Object> list = new LinkedList<>();
/** 设定count记录操作值 */
private AtomicInteger count = new AtomicInteger(0);
/** 队列为空 */
private final int minSize = 0;
/** 设定队列满值为5 */
private final int maxSize = 5;
private Object lock = new Object();
public void put(Object object){
synchronized (lock){
if(count.get() == maxSize){
try {
//如果队列已满,则该线程阻塞等到另一条线程取完值后进行通知
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.add(object);
count.incrementAndGet();
System.out.println("往里面加入元素"+object);
//put操作进行完毕,假设此时另一条线程进行取值阻塞,此时notify操作是必须要的
lock.notify();
}
}
public Object take(){
Object obj = null;
synchronized (lock){
if(count.get() == minSize){
try {
//如果队列已空,则该线程阻塞等到另一条线程进行玩put操作后进行通知
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
obj = list.removeFirst();
count.getAndDecrement();
System.out.println("往外面取出元素"+obj);
//take操作进行完毕,假设此时另一条线程进行put阻塞,此时notify操作是必须要的
lock.notify();
}
return obj;
}
}
测试代码开始就将该队列阻塞满,启动两条线程,线程1进行put操作,线程2进行take操作,如果线程1put操作发生在take操作后面则证明 线程1阻塞在put的时候
public class MyQueueDemo {
public static void main(String[] args) {
MyQueueTest queue = new MyQueueTest();
queue.put("a");
queue.put("b");
queue.put("c");
queue.put("d");
queue.put("e");
Thread thread1 = new Thread(()->{
queue.put("f");
queue.put("g");
});
Thread thread2 = new Thread(()->{
queue.take();
queue.take();
});
//休眠两秒后再启动线程2
thread1.start();
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread2.start();
}
}
运行结果显示线程2的take操作先于线程1的put操作 执行