浅谈多线程的数据处理工具(2020-11-29)

前言: volatile(可见性、有序性)

当变量被vilatile修饰时,对共享变量的读操作都在主内存中进行,其它线程进行修改会立即刷入主内存中。

Java中对引用类型变量的基本的读取、赋值是原子性的。
X=10: 原子性,
Y=X: 非原子性,
Y++: 非原子性,
z=z+1: 非原子性,

一、阻塞队列

BlockingQueue常见方法
方法名描述返回值
add()队尾添加元素,成功返回 true ,失败抛出异常。boolean
offer()队尾新添加元素。返回true表示添加成功,false表示添加失败,不会抛出异常(可延时操作)。boolean
put()向队列末尾新添加元素,如果队列已满,当前线程就等待(阻塞线程),响应中断异常。void
remove()移除头部元素,如果为null则抛出异常,也可移除已知元素。boolean
poll()移除头部元素并返回。如果null不会抛异常,会返回null(可延时操作)。E
element()获取头部元素,如果是null,抛出异常,不会删除元素。E
peek()获取头部元素,不会删除元素。E
take()如果队列为空则等待,否则移除头元素。E
remainingCapacity()还剩多少空间。int

ArrayBlockingQueue

数组结构组成的有界阻塞队列,创建时需指定大小。

LikedBlockingQueue

链表结构组成的有界队列,按照FIFO原则对元素排序,默认长度为Integer.MAX_VALUE。

PriorityBlockingQueue

支持线程优先级排序的无界队列,默认自然排序,也可实现compareTo()方法排序。

DelayQueue

延时获取的无界队列,创建元素时可指定多久后才可以从队列中获取元素。

SynchronousQueue

不储存元素,每次put必须等待take,否则不能添加元素,支持公平锁和非公平锁。

LinkedBlockingDeque

链表结构组成的双向阻塞队列,支持头尾操作。
LinkedBlockingDeque首位操作的方法
addFirst()addLast()
getFirst()getLast()
peekFirst()peekLast()
offerFirst()offerLast()

LinkedTransferQueue

链表构成的无界队列,多了transfer()、tryTransfer()在队尾插元素方法。
在队尾插元素,没有被消费,则等待。
queue.transfer("transfer");
queue.tryTransfer("tryTransfer");

二、Atomic类

AtomicInteger

内部依赖Unsafe类(由C++实现,内部存在大量汇编CPU指令等代码,),Unsafe的compareAndSwapInt采用CAS算法(会造成ABA问题),包含三个参数: 内存值V、旧的预期值A。要修改的新值B,
当A等于V时才修改(属于乐观锁)。

get()获取int
set()设置新值void
getAndIncrement()获取、加一int
addAndGet()加值、获取int
compareAndSet(10,20)根据比较结果设置boolean
doubleValue()转换为doubledouble

AtomicLong

与AutomicInteger相似,Unsafe的compareAndSwapLong多了SUPPORTS_NATIVE_CX8用来判断机器硬件和JVM版本是否支持8字节数字的cmpxchg操作,不支持则加锁(synchronized)保证原子性。

get()获取long
set()设置新值void
getAndSet()获取、更新long
getAndIncrement()获取、加一long
decrementAndGet()获取、减一long
addAndGet()加值、获取long
compareAndSet(10,20)根据比较结果设置boolean
doubleValue()转换为doubledouble

AtomicBoolean

内部本身用volatile修饰的int型成员变量。

get()获取值boolean
set()更新void
getAndSet()获取、设值boolean

AtomicIntegerArray

set(0,10) 设值 void
get(0)取值int
addAndGet(0,2)加值、获取int
decrementAndGet(0)减一、获取int
incrementAndGet(0)加一、获取int
getAndIncrement(0)获取、加一int
getAndDecrement(0)获取、减一int
updateAndGet(0,(i)->i+1)通过lambda 自由更改值int

AtomicReference

提供对象引用非阻塞原子性读写操作,CSA乐观方式。

import java.util.concurrent.atomic.AtomicReference;

public class Test005 {

    public static void main(String[]args){
        AtomicReference<Simple> atomic =new AtomicReference<>(new Simple("灭霸",18));
        Simple simple1 = atomic.get();
        System.out.println(simple1);
        atomic.set(new Simple("哥斯拉",19));
        Simple simple2 = atomic.getAndSet(new Simple("葫芦娃",22));
    }

    static class Simple{
        private String name;
        private int age;
        public Simple(){}
        public Simple(String name, int age) {
            this.name = name;
            this.age = age;
        }
        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;
        }

        @Override
        public String toString() {
            return "Simple{" +
                    "名字='" + name + '\'' +
                    ", 年龄=" + age +'}';
        }
    }
}

三、并发集合

1、CurrentMap(并发映射)

ConcurrentHashMap(代替HashMap)

1.8前分段(默认16个segement)锁机制,get不加锁用volatile保证可见性,put加锁控制在小范围内。
1.8后摒弃segement,直接用bucket,当链表长度超过8时转为红黑树,降低查询时间复杂度,采用CAS+synchronized保证安全性。底层数据结构为数组+链表/红黑树。

ConcurrentSkipListMap(代替TreeMap)

使用红黑树按照key的顺序(自然顺序、自定义顺序)来使得键值对有序存储的底层是通过跳表来实现的。

ConcurrentSkipListSet(代替TreeSet)

基于 ConcurrentSkipListMap 实现的,ConcurrentSkipListMap的键就不重复。

ConcurrentLinkedQueue(BlockingQueue)

通过无锁的方式,实现了高并发状态下的高性能,通常ConcurrentLikedQueue性能好于BlockingQueue。

ConcurrentLinkedDeque

ConcurrentLinkedQueue的升级版,非阻塞,无锁,无界 ,线程安全双端操作的队列。

2、CopyOnWrite(COW算法的容器)

CopyOnWrite容器读采用写分离思想,写时会先用显式锁整个容器(防止其它写线程),然后拷贝一份副本,对副本操作,读线程访问原容器数据。
内存开销大,实时数据一致性不高。适用于读远大于写操作,数据一致性要求不高的场景。

CopyOnWriteArrayList(替代ArrayList)

利用高并发往往是读多写少的特性,对读操作不加锁,对写操作,先复制一份新的集合,在新的集合上面修改,然后将新集合赋值。

CopyOnWriteArraySet

基于CopyOnWriteArrayList实现,其唯一的不同是在add时调用的是CopyOnWriteArrayList的addIfAbsent方法, 其遍历当前Object数组,如Object数组中已有了当前元素,则直接返回,如果没有则放入Object数组的尾部,并返回。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值