java.util.concurrent——BlockingQueue

java util concurrent 简述

JUC是JDK 1.5提供的一套专门用于并发编程的接口,帮助解决了并发环境下的一些问题

其他一些和并发相关的包有:
java.util.concurrent, java.util.concurrent.locks(锁相关), java.util.concurrent.atomic(原子性)

并发和并行

并发是值多个线程同时访问同一个资源
并行是指多个线程同时执行;所以并发是并行的一种。

JUC中包含的内容

BlockingQueue
ConcurrentMap
ExecutorService
Lock
Atomic

BlockingQueue

当我们需要用到队列,而且又是多线程环境,有希望能够有阻塞,可以考虑使用JUC的阻塞式队列

阻塞:程序执行时,如果无法得到预期结果,会hang住,不会往下执行,这个就叫做阻塞。
传统的Queue队列,队列已满时插入元素会报错;队列为空时获取元素会报错。
但是阻塞式队列,当队列已满时插入会等待;当队列为空时获取也会等待

阻塞队列具有的特点

1、遵循队列 FIFO(First In First Out) 的原则
2、具有 阻塞 的特点
3、队列都是定长的,这样才好控制阻塞,队列已满时。
4、不允许插入 null

常见方法

add 非阻塞方法,如果队列已满,添加元素是抛异常: IllegalStateException
offer(element) 非阻塞方法,如果队列已满,返回false值
put 阻塞,永久阻塞
offer(element,5,TimeUtil.SECOND) 定时阻塞,超时后返回false

remove 非阻塞,队列为空时,获取元素抛出异常 :NoSuchElementException
poll 非阻塞方法,队列为空时,返回null值
take 获取元素,永久阻塞
poll(5,TimeUtil.SECOND) 定时阻塞

代码演示

ArrayBlockingQueue

"阻塞式顺序队列"
"1、底层是数组"
"2、创建时需要指定容量,指定容量后大小不可变"

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;

public class BlockingQueueDemo {

    public static void main(String[] args) throws InterruptedException {

        // 需要指定容量,定长
        ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(5);

        // 添加元素
        queue.add("a");
        queue.add("a");
        queue.add("a");
        queue.add("a");
        queue.add("a");

        // 队列已满
        // 抛出异常 - IllegalStateException
        // queue.add("b");
        // 返回false
        // boolean flag = queue.offer("c");
        // System.out.println(flag);
        // 产生阻塞
        // queue.put("d");
        // 定时阻塞,返回false
        boolean flag = queue.offer("e", 3, TimeUnit.SECONDS);
        System.out.println(flag);
        System.out.println(queue);

    }

}

LinkedBlockingQueue

"底层是基于链式结构进行存储的——node"
"创建时可以指定容量,也可以不指定容量,如果指定了容量,那么容量不可变。"
"如果不指定容量,那么容量默认为Integer.MAX_VALUE,即21亿左右"

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

public class BlockingQueueDemo2 {

    public static void main(String[] args) throws InterruptedException {

        LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>();

        // 队列为空
        // 抛出异常 - NoSuchElementException
        // System.out.println(queue.remove());
        // 返回null
        // System.out.println(queue.poll());
        // 产生阻塞
        // System.out.println(queue.take());
        // 定时阻塞
        System.out.println(queue.poll(5, TimeUnit.SECONDS));

    }

}

PriorityBlockingQueue

带优先级的阻塞队列。

"底层是一个数组""
"如果不指定容量的话,默认容量是11"
"底层使用的数据结构其实是一个二叉堆,所以该队列会默认排序"
"该队列对于插入其中的元素,会实现默认排序"
"所以要求,放入到该队列中的元素必须实现Comparable接口,定义其中的比较规则CompareTo方法实现自然排序"
"创建队列时,可以传入一个比较器Comparator对象,重写其中的compare(o1,o2)方法,重新指定比较规则"

"比较原则类似,比较结果大于0,当前元素(前一个元素)和后一个元素进行交换,反之小于0不交换"

import java.util.Comparator;
import java.util.concurrent.PriorityBlockingQueue;

public class PriorityBlockingQueueDemo {

    public static void main(String[] args) throws InterruptedException {

        // PriorityBlockingQueue<String> queue = new PriorityBlockingQueue<>();
        // queue.put("g");
        // queue.put("a");
        // queue.put("r");
        // queue.put("u");
        // queue.put("w");
        // queue.put("l");
        // queue.put("o");

        /*
               for(){
                for(){
                    if(o1.compare(o2) > 0)
                        swap(o1, o2);
                }
               }
         */
        // 按照分数进行降序排序
        // Comparator<Student> c = new Comparator<Student>() {
        //     @Override
        //     public int compare(Student o1, Student o2) {
        //         return o2.getScore() - o1.getScore();
        //     }
        // };
        Comparator<Student> c = (s1, s2) -> s2.getScore() - s1.getScore();
        PriorityBlockingQueue<Student> queue = new PriorityBlockingQueue<>(5, c);

        queue.put(new Student("aaa", 50, 50));
        queue.put(new Student("bbb", 28, 59));
        queue.put(new Student("ccc", 35, 70));
        queue.put(new Student("dd", 18, 62));
        queue.put(new Student("eee", 40, 51));

        for (int i = 0; i < 5; i++) {
            System.out.println(queue.take());
        }

    }

}

class Student implements Comparable<Student> {

    private String name;
    private int age;
    private int score;

    public Student(String name, int age, int score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    // 指定比较规则
    // 如果this.compareTo(o)>0,那么this就排到o的后边
    // 如果this.compareTo(o)<0,那么this就排到o的前边
    // 在底层进行升序排序
    // 按照年纪升序排序
    // 升序排序:this - o
    // 降序排序:o - this
    @Override
    public int compareTo(Student o) {
        return this.age - o.age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
}

SynchronousQueue

同步阻塞队列,队列的长度不需要给定,底层默认是1而且只能是1

BlockingDeque

阻塞式双端队列,允许两头进两头出,是一个接口
因为两头可以操作,所以常用的操作方法有12个。
例如:
addFirst,addLast
offerFirst,offerLast
putFirst,putLast

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值