09.阻塞队列BlockingQueue接口

9.阻塞队列BlockingQueue接口

对于阻塞队列:

写入的时候如果队列满了,就必须阻塞等待消费。

读取的时候,如果队列是空的,就必须等待生产。

image-20200823233839904

BlockingQueue其实和ArrayList是同级的,其最初都继承自Collection

image-20200824000430448

9.1ArrayBlockingQueue的四种操作

方式抛出异常有返回值,不抛出异常阻塞 等待超时等待
添加addoffer()put()offer(,)
移除removepoll()take()poll(,)
检测队首元素elementpeek

(1)add(),remove()和element()

add(),remove()在队列满了继续存或者,空了继续取的时候会抛出异常。

element()查看队首元素。add()添加成功返回true,队列满了继续存会添加失败会异常。remove()删除成功会返回元素,空了继续取的时候会抛出异常。

/**
 * 抛出异常
 */
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"));
    // IllegalStateException: Queue full 抛出异常!
     System.out.println(blockingQueue.add("d"));
    System.out.println("=-===========");
    System.out.println(blockingQueue.element()); // 查看队首元素是谁
    System.out.println(blockingQueue.remove());
    System.out.println(blockingQueue.remove());
    System.out.println(blockingQueue.remove());

    // java.util.NoSuchElementException 抛出异常!
     System.out.println(blockingQueue.remove());
}

(2)offer,poll(),peek()

peek()查看队首元素。offer()添加成功返回true,队列满了继续存会添加失败会返回false。poll()删除成功会返回元素,空了继续取的时候会返回null。

/**
 * 有返回值,没有异常
 */
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.peek());
    // System.out.println(blockingQueue.offer("d")); // false 不抛出异常!
    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)put()和take()

put添加不进去会一直阻塞,程序就一直停在那了。

take()如果最终在队列里面没有元素可以取了,就会一直阻塞。

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)对offer和poll正确做法

加入参数数字和TimeUnit.SECONDS这样就能让程序超时等待,等待一会,看后面有什么操作,执行下一步

/**
 * 等待,阻塞(等待超时)
 */
public static void test4() throws InterruptedException {
    // 队列的大小
    ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);

    blockingQueue.offer("a");
    blockingQueue.offer("b");
    blockingQueue.offer("c");
    // blockingQueue.offer("d",2,TimeUnit.SECONDS); // 等待超过2秒就退出
    System.out.println("===============");
    System.out.println(blockingQueue.poll());
    System.out.println(blockingQueue.poll());
    System.out.println(blockingQueue.poll());
    blockingQueue.poll(2, TimeUnit.SECONDS); // 等待超过2秒就退出
}

9.2SynchronousQueue同步队列

BlockingQueue接口下的一个实现类。

这是一个同步队列

put了一个元素,必须从里面先take取出来,否则不能在put进去值,比如下面这个就是一个线程put完后,一个线程take。

import java.sql.Time;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;

/**
 * 同步队列
 * 和其他的BlockingQueue 不一样, SynchronousQueue 不存储元素
 * put了一个元素,必须从里面先take取出来,否则不能在put进去值!
 */
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();
    }
}

image-20200824091305502

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值