多线程基础

Amos Xia, 2018-06-13 08:28:20

java.util.concurrent里提供了很多用于并发的组件.

可以传递给Thread进行异步执行的对象:

  • Runnable, 用于封装没有参数和返回值的异步方法
  • Callable, 用于封装没有参数, 但有返回值的异步方法
  • Future, 保存了异步方法执行的状态和结果
  • FutureTask, 实现了Future和Runnable的接口, 可用来转换Callable到Runnable

Thread的6种状态变化

一个runnable状态的线程可能正在运行, 也可能没有运行.

实现UncaughtExceptionHandler接口, 然后可以通过setUncaughtExceptionHandler方法为线程指定异常处理器. 也可以通过Thread.setDefaultUncaughtExceptionHandler为所有线程设置默认的异常处理器.

同步

如果多个线程同时对某个数据进行请求, 则会产生竞争条件, 此时就需要通过同步的手段来使这些请求串行化处理.

Java的每个对象都有一个内部锁, 并且该锁有一个内部的条件变量.

Java的同步策咯:

    • synchronized方法, synchronized使用的就是对象的内部锁
    • ReentrantLock
    • condition variable条件变量
  • 同步阻塞, synchronized到对象, 显式加锁, 尽量保证锁的范围尽可能小
  • 监视器
  • 原子操作, java.util.concurrent.atomic提供了很多原子操作的工具
  • java.util.concurrent提供了线程安全的集合

任何集合类可以通过使用Collections.synchronizedXXX同步包装器方法变成线程安全. 但尽量使用java.util.concurrent提供的线程安全的集合, 而不是使用同步包装器方法.

List<E> list = Collection.synchronizedList(new ArrayList<E>());
Map<K, V> map = Collection.synchronizedMap(new HashMap<K, V>());

线程池

通过Executor执行器来创建线程池, 返回ExecutorService.

  • newCachedThreadPool, 只在必要时创建新线程; 空闲线程只会保留一定时间后释放
  • newFixedThreadPool, 固定数量的线程
  • newScheduledThreadPool, 预定时间执行的固定线程池, 用来替代Timer来处理定时任务

当调用ExecutorService.shutdown时, Executor不再接受新任务, 等所有已存在的任务执行完毕后, 释放所有线程; 而shutdownNow则会立即中断所有正在执行的线程.

Fork-Join 框架

Java7 引入了Fork-Join框架.

Java8的stream流处理的底层并发框架默认使用Fork-Join框架.

Fork-Join使用work stealing工作窃取的方法来平衡可用线程的工作负载.


知识共享许可协议
本作品采用知识共享署名 4.0 国际许可协议进行许可。


Copyright© 2018 s2u2m