Java并发基础知识

Java并发基础知识

Scroll Down

线程池

线程池的分类及使用场景

CachedThreadPool

介绍: 特点是没有核心线程, 当线程池的最大尺寸设为最大整型时, 线程可以无限创建, 当线程池中的线程都处于活动状态时, 就会创建新的线程来处理新的任务, 否则使用空闲的线程来处理新任务, 这种线程池的线程的keepAliveTime是有效的,一般线程空闲超过60秒会被回收; 任务队列采用的是SynchronousQueue, 这个队列是无法插入任务的, 因为线程池只要有任务就会立马去执行, 所以不需要任务队列来保存任务

使用场景: 适合任务量大, 但耗时少的任务

FixedThreadPool

介绍: 特点是全是核心线程, 也没有超时机制, 任务大小也是没有限制的, 除非线程池关闭, 否则即使线程空闲了也不会被回收, 所以创建该线程池主要需要两个参数, 一个是核心线程数, 一个是线程工厂, keepAliveTime无效; 任务队列采用的是LinkedBlockingQueue, 当有新任务提交时, 如果有线程空闲则执行, 否则阻塞在任务队列中, 有空闲线程的时候再去执行队列中的任务

使用场景: 使用于任务量比较固定但耗时长的任务

ScheduledThreadPool

介绍: 核心线程数量固定, 但非核心线程没有限制, 非核心线程一闲置就会被回收, keepAliveTime无效, 因为核心线程是不会被回收的, 当运行的线程数没有达到核心线程数时就新建线程去DelayedWorkQueue中取ScheduledFutureTask然后执行任务, 否则就将任务在DelayedWorkQueue排序, 然后一个个创建非核心线程去执行, 执行完线程就会被回收, 任务队列就是采用的DelayedWorkQueue, 这是个无界队列

使用场景: 该线程池用于执行定时任务和具体固定周期性任务

SingleThreadExecutor

介绍: 只有一个核心线程的线程池, 任务队列采用的是 LinkedBlockingQueue

使用场景: 用于处理多任务顺序执行, 不用处理线程同步的问题

SingleThreadScheduledExecutor

介绍: 创建一个单线程可执行延迟任务的线程池, 其实就是核心线程数为1的ScheduledThreadPool

WorkStealingPool

介绍: 抢占式执行线程池, 任务执行顺序不确定

Java锁

CAS: (Check And Set), 在更新之前先检查某个值, 再更新

例如: 20 --> 50 先检查值是否为20, 如果是将其更新为50

ABA问题: 再检查值是否为20之前, 该值很可能已经由 20 ---> 其他值 ---> 20 所以, 就很可能导致错误更新, 解决办法就是加入一个版本字段, 每次更新时检查在更新之前有没有其他线程更新过, 每次更新后版本+1

偏向锁 / 轻量级锁 / 重量级锁

偏向锁: 就是这锁没什么用, 对于这把锁不存在竞争, 其实是没必要上锁的, 只是打个标记而已

轻量级锁: 指的是当锁原来是偏向锁的时候, 被另一个线程访问, 说明存在竞争, 那偏向锁就会升级为轻量级锁, 线程会通过自旋的方式尝试获取锁, 而且不会陷入阻塞

重量级锁: 也就是互斥锁, 利用操作系统的同步机制实现, 开销相对较大; 当多个线程竞争同一个轻量级锁时, 且竞争的时间长, 锁就会膨胀为重量级锁, 重量级锁会让其他拿不到锁的线程进入阻塞状态

可重入锁 / 非可重用锁

可重入锁: 线程已经持有锁A, 能在不释放锁A的情况下再次获取锁A

不可重入锁: 与可重入锁相反, 已经持有锁A, 要再次获取需要先释放再获取

共享锁 / 独占锁

共享锁: 同一把锁可以被多个线程同时获得

独占锁: 同一把锁只能被一个线程获取

公平锁 / 非公平锁

公平锁: 拿不到锁的线程, 会进入等待队列, 等待时间越长的线程会优先拿到, 也就是先来先得

非公平锁: 就是在一定情况下可能会插队

悲观锁 / 乐观锁

悲观锁: 获取资源之前先拿到锁, 锁住资源

乐观锁: 不会去获取锁, 在操作资源时会先检查在修改(CAS)

自旋锁 / 非自旋锁

自旋锁: 在未获取到锁的情况下, 会不断的尝试获取锁

非自旋锁: 拿不到锁就直接放弃, 进入等待或阻塞

可中断锁 / 不可中断锁

可中断锁: 开始申请锁之后, 未获取到锁之前可以放弃获取锁

不可中断锁: 一旦开始申请锁, 就不必须要等锁获取到了才能进行以后的操作

并发容器(不一定加锁, 可能通过CAS实现)

ConcurrentHashMap:并发版HashMap

CopyOnWriteArrayList:并发版ArrayList (写入时先复制, 然后修改新的, 再将原来的指向新的, 也就是读写分离)

CopyOnWriteArraySet:并发Set

ConcurrentLinkedQueue:并发队列(基于链表)

ConcurrentLinkedDeque:并发队列(基于双向链表)

ConcurrentSkipListMap:基于跳表的并发Map

ConcurrentSkipListSet:基于跳表的并发Set

阻塞队列(加锁阻塞)

ArrayBlockingQueue:阻塞队列(基于数组)

LinkedBlockingQueue:阻塞队列(基于链表)

LinkedBlockingDeque:阻塞队列(基于双向链表)

PriorityBlockingQueue:线程安全的优先队列

LinkedTransferQueue:基于链表的数据交换队列

SynchronousQueue:读写成对的队列(容量为0), 获取时先阻塞, 直到有数据放入

DelayQueue:延时队列

原子类(操作具备原子性的类)

AtomicBoolen: boolean类型原子类

AtomicInteger: int类型原子类

AtomicLong: long类型原子类

AtomicIntegerArray:Int数组类型原子类

AtomicLongArray:long数组类型原子类

AtomicReferenceArray:引用类型数组原子类

AtomicReference:引用类型原子类

AtomicMarkableReferenceAtomicReference升级版, 加上了时间戳, 用于解决CAS的ABA问题

AtomicStampedReference:与AtomicReference类似, 多绑定了一个布尔值, 用于表示该对象是否已删除 (咋整的跟数据库逻辑删除差不多呢)

AtomicIntegerFieldUpdater: 原子更新器, 用于原子更新非原子整型

AtomicLongFieldUpdater: 原子更新器, 用于原子更新非原子长整型

AtomicReferenceFieldUpdater:原子更新器, 用于原子更新非原子应用

Adder: 加法器

Accumulator: 累积器

ThreadLocal

Future