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();
    }
    
}
  1. 抛出异常



/**
 * 抛出异常
 */
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
  1. 有返回值,没有异常
/**
 * 有返回值,不抛出异常
 */
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
  1. 等待,阻塞(一直阻塞)
/**
 * 等待,阻塞(一直阻塞)
 */
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
测试是否等待!

  1. 等待,阻塞(超时等待)
/**
 * 等待,阻塞(等待超时)
 */
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
posted @ 2020-05-26 22:53  我有满天星辰  阅读(1)  评论(0编辑  收藏  举报