原子性操作
解释:原子性是指一个操作是不可中断的,要么全部执行成功要么全部执行失败,有着“同生共死”的感觉。即使在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程所干扰
一、原子性方法
java.util.concurrent.atomic包
- AtomicInteger类提供了方法
incrementAndGet和decrementAndGet,它们分别以原子方式将一个整数自增或自减 - 实现跟踪不同线程是否在操作~
compareAndSet方法会映射到一个处理器操作,比使用锁速度更快 updateAndGet()和accumulateAndGet()~利用二元操作符来合并操作原子值和所提供的参数getAndUpdate()和getAndAccumulate()~可以返回原值
如果有大量线程要访问使用~LongAdder和LongAccumulator类
二、线程局部变量
简介:有时可能要避免共享变量,使用ThreadLocal类为各个线程提供各自的实例。
- static
ThreadLocalwithInitial(Supplier<?extends S>supplier)创建一个线程局部变量,其初始值通过调用给定的supplier生成。 protected initialize()~~应覆盖这个方法来提供一个初始值。默认情况下,这个方法返回null。Tget()~~得到这个线程的当前值。如果是首次调用get,会调用initialize来得到这个值。voidset(T t)~~为这个线程设置一个新值。voidremove()~~删除对应这个线程的值。static ThreadLocalRandomcurrent()~~返回特定于当前线程的Random类实例(生成随机数)
为什么弃用stop和suspend方法
stop方法,该方法直接终止该线程相关的所有未结束的方法
- 在希望停止线程的时候应该中断线程,被中断的线程会在安全的时候停止。
suspend方法,挂起一个持有一个锁的线程,那么,该锁在恢复之前是不可用的,造成阻塞
- 安全地挂起线程,可以引入一个变量suspendRequested并在run方法的某个安全的地方测试它,
- 安全的地方是指该线程没有封锁其他线程需要的对象的地方。当该线程发现suspendRequested变量已经设置,将会保持等待状态直到它再次获得为止。
阻塞队列
简介:不需要显式的线程同步,这也是一种同步机制。java.util.concurrent.BlockingQueue:
在一个多线程程序中,队列会在任何时候空或满,因此,一定要使用offer、poll和peek方法作为替代,即插入null是非法的
java.util.concurrent
LinkedBlockingQueue的容量是没有上边界的,但是,也可以选择指定最大容量- LinkedBlockingDeque是一个双端的
ArrayBlockingQueue在构造时需要指定容量- 并且有一个可选的参数来指定是否需要公平性。则那么等待了最长时间的线程会优先得到处理
PriorityBlockingQueue是一个带优先级的队列,用堆实现。DelayQueue包含实现Delayed接口的对象- getDelay方法返回对象的残留延迟(设置延时)。负值表示延迟已经结束。元素只有在延迟用完的情况下才能从DelayQueue移除。还必须实现compareTo方法。DelayQueue使用该方法对元素进行排序。
TransferQueue接口,该线程等待另一个线程执行完~LinkedTransferQueue类实现了这个接口。
线程安全的集合
java.util.concurrent
ConcurrentHashMap、ConcurrentSkipListMap、ConcurrentSkipListSet和ConcurrentLinkedQueue
mappingCount()方法可以把大小作为long返回(类似size()方法)- 集合返回弱一致性的迭代器。所以迭代器不一定能反映出它们被构造之后的所有的修改,但是,它们不会将同一个值返回两次,也不会抛出Concurrent ModificationException异常
- 集合如果在迭代器构造之后发生改变,java.util包中的迭代器将抛出ConcurrentModificationException异常
更新映射
ConcurrentHashMap可以实现原子更新,ConcurrentHashMap中不允许有null值
- get和put方法不会破坏数据结构。不过,由于操作序列不是原子的,所以结果不可预知
- 使用replace操作,它会以原子方式用一个新值替换原值,前提是之前没有其他线程把原值替换为其他值
putIfAbsent()返回映射的的值(可能是原来的值,或者是新设置的值)compute()方法时可以提供一个键和一个计算新值的函数。
computeIfPresent()、computeIfAbsent(),分别只在已经有原值的情况下计算新值,或者只有没有原值的情况下计算新值merge方法,有一个参数表示键不存在时使用的初始值。否则,就会调用你提供的函数来结合原值与初始值,这个函数不处理键- 传入compute或merge的函数返回null,将从映射中删除现有的条目
散列映射的批量操作
search为每个键或值提供一个函数,直到函数生成一个非null的结果。然后搜索终止,返回这个函数的结果reduce组合所有键或值,这里要使用所提供的一个累加函数forEach为所有键或值提供一个函数
上述操作的对应方法
#需要指定一个参数化阈值。如果映射包含的元素多于这个阈值,就会并行完成批操作
#将结果作为int、long和double输出,方法后缀加ToInt、ToLong和ToDouble即可
- operationKeys:处理键。
- operationValues:处理值。
- operation:处理键和值。
- operationEntries:处理Map.Entry对象。
并发集视图
- 静态newKeySet方法会生成一个Set
- keySet方法可以生成这个映射的键集。可以删除键并把值一并删除,不能执行添加操作
- Java SE 8为ConcurrentHashMap增加了第二个keySet方法,形参传入一个默认值,在为集增加元素时使用
数组拷贝
- CopyOnWriteArrayList和CopyOnWriteArraySet
算法操作
- 静态Arrays.parallelSort方法可以对一个基本类型值或对象的数组排序
- parallelSetAll方法会用由一个函数计算得到的值填充一个数组
parallelPrefix方法,它会用对应一个给定结合操作的前缀的累加结果替换各个数组元素
Vector
简介:Vector和Hashtable类就提供了线程安全的动态数组和散列表的实现。现在这些类被弃用了,
取而代之的是ArrayList和HashMap类任何集合类都可以通过使用同步包装器变成线程安全的
- List
> list = Collections.singletonList(new ArrayList());
- 如果在另一个线程可能进行修改时要对集合进行迭代,仍然需要使用对象方法锁
异步操作
Callable与Future
简介:Runnable封装一个异步运行任务,Callable与Runnable类似,但是有返回值。Callable接口是一个参数化的类型,只有一个方法call
Future
简介:Future保存异步计算的结果。进行一个计算,将Future对象交给某个线程,Future对象的所有者在结果计算好之后就可以获得它
get()~调用后被阻塞,直到计算完成。可以设置超时,超时会报异常,如果该方法的线程被中断会报异常isDone()~检测是否在计算是否结束cance()~法取消该计算
FutureTask包装器
简介:可将Callable转换成Future和Runnable,它同时实现二者的接口
线程池

newCachedThreadPool()~对于每个任务,如果有空闲线程可用,立即让它执行任务,如果没有可用的空闲线程,则创建一个新线程。newFixedThreadPool()~如果提交的任务数多于空闲的线程数,那么把得不到服务的任务放置到队列中。当其他任务完成以后再运行它们。newSingleThreadExecutor()由一个线程去执行提交的任务,一个接着一个执行。
一、创建线程池
ExecutorService service = Executors._newCachedThreadPool_();
二、获取线程
service.submit(new Thread());- 调用submit时,会得到一个Future对象,可用来查询该任务的状态,或者可以使用这个对象来调用isDone、cancel或isCancelled。但是,get方法在完成的时候只是简单地返回null
三、关闭线程池
shutdown,被关闭的执行器不再接受新的任务。当所有任务都完成以后,线程池中的线程死亡。shutdownNow,该池取消尚未开始的所有任务并试图中断正在运行的线程- 注意:如果提交Callable对象,那就要保存好返回的Future对象
预执行
简介:ScheduledExecutorService接口具有为预定执行或重复执行任务而设计的方法
使用:设置延时执行的时间或重复执行的周期
创建:Executors类的newScheduledThreadPool和newSingleThreadScheduledExecutor方法
- 返回实现了Scheduled-ExecutorService接口的对象
控制任务组
简介:控制一组相关任务
- invokeAny方法提交所有对象到一个Callable对象的集合中,并返回某个已经完成了的任务的结果。
- 这个方法的缺点是如果第一个任务恰巧花去了很多时间,则可能不得不进行等待全部完成。

- 将结果按可获得的顺序保存。可以用
ExecutorCompletionService来对结果进行排列。

