阻塞队列
阻塞线程可以协调多个线程之间的合作。
对于许多线程问题,可以通过使用一个或多个队列将其形式化, 生产者线程向队列插入元素,消费者线程则取出元素。
当试图向队列添加元素而队列已满,或者想从队列移出元素而队列为空时,阻塞队列导致线程阻塞。
阻塞队列的方法可以分为以下三类,取决于当队列满或空时它们的响应方式:
- put(),take(),当队列满或空时阻塞。
- add(),element(),remove(),当队列满或空时抛出异常
- offer(),peek(),poll(),返回boolean或null。可以加超时参数
java.util.concurrent包提供的阻塞队列:
- LinkedBlockingQueue,
- LinkedBlockingDeque,首尾双端版本
- ArrayBlockingQueue,
- PriorityBlockingQueue,
- DelayedQueue
线程安全的集合
java.util.concurrent包提供了线程安全的映射、有序集、队列的高效实现。ConcurrentHashMap,ConcurrentSkipListMap,ConcurrentSkipListSet,ConcurrentLinkedQueue。这些集合使用复杂的算法,通过允许并发访问数据结构的不同部分来使竞争最小化。
size()不必在常规时间内返回,确定这样集合的大小需要遍历。对于庞大的并发散列映射,mappingCount()可以把大小作为long型返回。
集合返回弱一致性的迭代器,迭代器不一定能反映出它们被构造之后的所有修改,会尽量返回所有修改,但是它们不会将一个值返回两次,不会抛出ConcurrentModificationException异常。
并发的散列集合,可高效的支持大量的读者和一定数量的写者。
原子更新
replace(K key, V oldValue, V newValue); 替换动作
compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction); 提供键和一个计算新值的函数
merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction); value表示键不存在时的初始值
批操作
Java SE 8为并发散列映射提供了批操作,即使有其他线程在处理映射,也能安全执行。
批操作会遍历映射,处理遍历过程中找到的元素。
共三种不同的操作:
search搜索,为每个键或值提供一个函数,知道函数返回一个非null的结果
reduce归约,组合所有的键或值
forEach
并发集视图
没有ConcurrentHashSet,用ConcurrentHashMap创建
//使用newKeySet()创建线程安全的集
Set<String> words = ConcurrentHashMap.newKeySet();
Set<String> words = map.keySet("5");
words.add("e")
//已存在的映射的生成线程安全的集
Set<String> words = map.keySet("5");
words.remove("d");
words.add("e");
写数组的拷贝
CopyAndWriteArrayList,CopyAndWriteArraySet
所有的修改线程对底层数组进行复制。
并行数组算法
Arrays提供了大量的并行化操作。
parallelSort(int[] a),对一个基本类型或对象的数组排序
parallelSort(int[] a, int fromIndex, int toIndex),指定排序的边界
parallelSetAll(T[] array, IntFunction<? extends T> generator),用函数计算的值填充数组
callable与future
Runnable封装一个异步运行的任务,没有参数和返回值
Callable,可以包含参数
Future保存异步计算的结果,
FutureTask同时实现了Callable,Runnable
线程池
Executors.newCachedThreadPool(),
Executors.newFixedThreadPool()
Executors.newSingleThreadPool()
Executors.newScheduledThreadPool(),提供方法可以预定执行任务,或重复执行任务
Executors.newSingleThreadScheduledThreadPool()
使用完线程池后需要执行shutdown()关闭线程池