1.并发框架Executor
- JDK 5开始提供Executor FrameWork (java.util.concurrent.*)
- 分离任务的创建和执行者的创建
- 线程重复利用(new线程代价很大)
共享线程池
- 预设好的多个Thread,可弹性增加
- 多次执行很多很小的任务
- 任务创建和执行过程解耦
- 程序员无需关心线程池执行任务过程
主要类
- Executors.newCachedThreadPool/newFixedThreadPool 创建线程池
- ExecutorService 线程池服务
- Callable 具体的逻辑对象(线程类)
- (Runnable的run方法没有返回值,而Callable的call方法可以有返回值)
- Future 返回结果
1 | //创建可变线程池 |
2.并发框架Fork-join
- Java 7 提供另一种并行框架:分解、治理、合并(分治编程)
- 适合用于整体任务量不好确定的场合(最小任务可确定)
主要类
- ForkJoinPool 任务池
- RecursiveAction
- RecursiveTask
1 | //创建执行线程池 |
3.并发数据结构
常用的数据结构是线程不安全的
- ArrayList, HashMap, HashSet 非同步的
- 多个线程同时读写,可能会抛出异常或数据错误
传统Vector,Hashtable等同步集合性能过差
并发数据结构:数据添加和删除
- 阻塞式集合:当集合为空或者满时,等待
- 非阻塞式集合:当集合为空或者满时,不等待,返回null或异常
List
- Vector 同步安全,写多读少
- ArrayList 不安全
- Collections.synchronizedList(List list) 基于synchronized,效率差
- CopyOnWriteArrayList 读多写少,基于复制机制,非阻塞
Set
- HashSet 不安全
- Collections.synchronizedSet(Set set) 基于synchronized,效率差
- CopyOnWriteArraySet (基于CopyOnWriteArrayList实现) 读多写少,非阻塞
Map
- Hashtable 同步安全,写多读少
- HashMap 不安全
- Collections.synchronizedMap(Map map) 基于synchronized,效率差
- ConcurrentHashMap 读多写少,非阻塞
Queue & Deque (队列,JDK 1.5 提出)
- ConcurrentLinkedQueue 非阻塞
- ArrayBlockingQueue/LinkedBlockingQueue 阻塞
4.并发协作控制
Lock
- Lock也可以实现同步的效果
- 实现更复杂的临界区结构
- tryLock方法可以预判锁是否空闲
- 允许分离读写的操作,多个读,一个写
- 性能更好
- ReentrantLock类,可重入的互斥锁
- ReentrantReadWriteLock类,可重入的读写锁
- lock和unlock函数
1 | //构造锁 |
Semaphore
- 信号量:本质上是一个计数器
- 计数器大于0,可以使用,等于0不能使用
- 可以设置多个并发量,例如限制10个访问
- Semaphore
- acquire获取
- release释放
- 比Lock更进一步,可以控制多个同时访问关键区
1 | //构造信号量 |
Latch
- 等待锁,是一个同步辅助类
- 用来同步执行任务的一个或者多个线程
- 不是用来保护临界区或者共享资源
- CountDownLatch
- countDown() 计数减1
- await() 等待latch变成0
1 | //构造等待锁 |
Barrier
- 集合点,也是一个同步辅助类
- 允许多个线程在某一个点上进行同步
- CyclicBarrier
- 构造函数是需要同步的线程数量
- await等待其他线程,到达数量后,就放行
1 | //当有3个线程在barrier上await,就执行finalResultCalculator中的run方法 |
Phaser
- 允许执行并发多阶段任务,同步辅助类
- 在每一个阶段结束的位置对线程进行同步,当所有的线程都到达这步,再进行下一步
- Phaser
- arrive()
- arriveAndAwaitAdvance()
1 | //构造 |
Exchanger
- 允许在并发线程中互相交换消息
- 允许在2个线程中定义同步点,当两个线程都到达同步点,它们交换数据结构
- Exchanger
- exchange(), 线程双方互相交互数据
- 交换数据是双向的
1 | //构造,交换类型为String |
5.定时任务执行
简单定时器机制
- 设置计划任务,也就是在指定的时间开始执行某一个任务。
- TimerTask 封装任务
- Timer类 定时器
1 | /* |
Executor +定时器机制
- ScheduledExecutorService
- 定时任务
- 周期任务
1 | //固定时间(1s后)启动 |
Quartz
- Quartz是一个较为完善的任务调度框架
- 解决程序中Timer零散管理的问题
- 功能更加强大
- Timer执行周期任务,如果中间某一次有异常,整个任务终止执行
- Quartz执行周期任务,如果中间某一次有异常,不影响下次任务执行
- ……
1 | import org.quartz.JobDetail; |