Current并发包(一)

Concurrent包

是JDK1.5提供的并发包

Concurrent包主要包含了5块内容

BlockingQueue - 阻塞式队列

ConcurrentMap - 并发映射

ExecutorService -执行器服务

Lock -原子性操作

BlockingQueue - 阻塞式队列

本身是一个队列 -用于对线程进行生产和消费

满足队列FIFO的特点

阻塞队列都是有界的,所有的阻塞式队列的大小是固定

如果队列已满,则添加的元素会被阻塞,直到队列中有元素被取出

如果队列为空,则获取元素的线程会被阻塞,直到队列中被添加元素

阻塞队列适合于生产消费模型

阻塞队列中要求元素非空

实现类

ArrayBlockingQueue - 阻塞式顺序队列

底层是基于数组来进行存储

在使用的时候需要指定容量,并且容量指定之后是不可变的

 

LinkedBlockingQueue - 阻塞式链式队列

底层是基于链表实现

容量可以不指定,默认容量:Integer.MAX_VALUE,即2^31-1

一般不会向一个队列中添加21亿个值,认为无界

 

PriorityBlockingQueue - 具有优先级的阻塞式队列

在使用的时候如果不指定容量,则默认容量为11

在遍历元素的时候是有序的

要求元素必须实现Comparable接口

实现的排序称之为是自然排序

SynchronousQueue - 同步队列

在使用的时候不需要指定容量。默认容量是1并且只能为1

扩展

BlockingDeque

阻塞式双向队列 - 允许从两端放或者拿元素

 抛出异常返回值长期阻塞定时阻塞
add offer - false put offer
remove poll - null take poll
BlockingQueueDemo.java

添加元素

queue.add("f");

队列已满,抛出异常

queue.offer("g");

队列已满,返回false

queue.put("h")

队列已满,阻塞(永久)

queue.offer("r", 5, TimeUnit.SECONDS);

队列已满,定时阻塞

package com.wiscom.queue;
​
public class BlockingQueueDemo {
​
    public static void main(String[] args) throws InterruptedException {
​
        ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(5);
​
        // 添加元素
        queue.add("a");
        queue.add("b");
        queue.add("c");
        queue.add("d");
        queue.add("e");
​
        // 队列已满,抛出异常
        // queue.add("f");
        
        // 队列已满,返回false
        // boolean b = queue.offer("g");
        
        // 队列已满,产生阻塞
        // queue.put("h");
        
        // 队列为空,定时阻塞
        queue.offer("r", 5, TimeUnit.SECONDS);
        System.out.println(queue);
    }
}
BlockingQueueDemo2.java

取出元素

queue.remove()

队列为空,抛出异常

queue.poll()

队列为空,返回null

queue.take()

队列为空,阻塞(永久)

queue.poll(5, TimeUnit.SECONDS)

队列为空,定时阻塞

package com.wiscom.queue;
​
public class BlockingQueueDemo2 {
​
    public static void main(String[] args) throws InterruptedException {
​
        // ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(5);
        LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>();
​
        // 队列为空,抛出异常
        // System.out.println(queue.remove());
        
        // 队列为空,返回null
        // System.out.println(queue.poll());
        
        // 队列为空,产生阻塞
        // System.out.println(queue.take());
        
        // 队列为空,定时阻塞
        System.out.println(queue.poll(5, TimeUnit.SECONDS));
    }
}
PriorityBlockingQueueDemo.java
package com.wiscom.queue;
​
public class PriorityBlockingQueueDemo {
​
    public static void main(String[] args) throws InterruptedException {
​
        // PriorityBlockingQueue<String> queue = new PriorityBlockingQueue<>(7);
        //
        // queue.put("g");
        // queue.put("a");
        // queue.put("r");
        // queue.put("h");
        // queue.put("d");
        // queue.put("t");
        // queue.put("u");
​
        PriorityBlockingQueue<Student> queue = new PriorityBlockingQueue<>(5);
​
        queue.put(new Student("曹洋", 80, 59));
        queue.put(new Student("李帅", 30, 61));
        queue.put(new Student("孟祥冰", 40, 19));
        queue.put(new Student("肖旭伟", 40, 70));
        queue.put(new Student("谷丰硕", 18, 30));
​
        // for (int i = 0; i < 7; i++) {
        // System.out.println(queue.take());
        // }
        for (Student s : queue) {
            System.out.println(s);
        }
    }
​
}
​
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;
    }
​
    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + ", score=" + score + "]";
    }
​
    // 按照年龄进行升序排序
    // this - o ===> 升序
    // o - this ===> 降序
    @Override
    public int compareTo(Student o) {
        return this.age - o.age;
    }
​
}
 

ConcurrentMap - 并发映射

本质上是一个Map,依然以键值对结构来存储数据

ConcurrentMap提供了并发并且安全的方式来读写数据

 

ConcurrentHashMap - 并发哈希映射

Hashtable

对外界提供的方法都是同步非静态方法的锁对象

同步非静态方法的锁对象是this --— this 当前对象 --— Hashtable是以当前对象作为锁对象

底层是基于数组+链表存储,默认初始容量为16

默认加载因子是0.75

每次扩容默认增加一倍

ConcurrentHashMap

是一个异步式线程安全的映射

引入了分段 (桶)锁 机制来解决Hashtable所带来的效率降低的问题

在后续JDK版本中,ConcurrentHashMap在分段锁的基础上引入了读写锁来提高效率

读锁:允许多个线程读,不允许线程写

写锁:只能允许一个线程写,不允许线程读

在JDK1.8中

ConcurrentHashMap引入了CAS(Compare And Swap,比较和交换)无锁算法

无锁算法保证异步线程安全

CAS算法需要与具体的内核结合

目前几乎所有的内核架构都是支持CAS

CAS的语义

我认为V的值应该是A,如果是,那么将V的值更新为B

否则不修改并告诉V的值实际为多少

V:内存值

A:旧的预期值

B:新的预期值

CAS 过程中只要被打断,那么所有过程从头再来

posted @ 2020-08-21 17:30  minnersun  阅读(406)  评论(0编辑  收藏  举报