对象的共享
- volatile
同步容器类
Collections.sychronizedXXX();
- 迭代时修改会引发ConcurrentModificationException异常,因为modCount有变化
并发容器
- ConcurrentHashMap:使用一种粒度更细的加锁机制来实现更大程度的共享,称为分段锁;其迭代器具有弱一致性,而不是快速失败。
- CopyOnWriteList:每次修改时都会创建并重新发布一个新的容器副本,从而实现可变性,迭代操作远远多于修改操作时使用。
- 阻塞队列和生产者-消费者模式()
- Executor任务执行框架中就体现了这种模式
- BlockingQueue的三种实现:LinkedBlockingQueue、ArrayBlockingQueue、PriorityBlockingQueue、SynchronousBlockingQueue
- 双端队列:Deque、BlockingDeque
同步工具类
闭锁
- CountDownLatch
public long timeTasks(int nThreads, final Runnable task) throws InterruptedException{
final CountDownLatch startGate = new CountDownLatch(1);
final CountDownLatch endGate = new CountDownLatch(nThreads);
for(int i = 0; i < nThreads; i++) {
Thread t = new Thread(){
public void run(){
try {
startGate.await();
try {
task.run();
} finally {
endGate.countDown();
}
}
}
}
}
long start = System.nanoTime();
startGate.countDown();
emdGate.await();
long end = System.nanoTime();
return end-start;
}
- FutureTask
实现了Future语义,通过Callable来实现,有三种状态:等待运行、正在运行、运行完成。Future.get的行为取决于任务的状态,如果任务完成,get会立即返回结果,否则阻塞到任务进入完成状态。FutureTask在Executor框架中表示异步任务。
FutureTask<Product> future = new FutureTask<Product>(new Cllable<Product>){
public Product call() throws DataLoadException {
return load();
}
}
return future.get;
- 信号量Semaphore
Semaphore可以用于实现资源池,例如数据库连接池。
Semaphore sem = new Semaphore();
sem.acquire();
sem.release();
- 栅栏Barrier
闭锁用于等待事件,栅栏用于等待线程,CyclicBarrier可以使一定数量的参与方反复的在栅栏位置汇集。
CylicBarrier barrier = new CylicBarrier(count, new Runnable() {
public void run() {
mainBoard.commitNewValues();
}
});
barrier.await();
另一种形式的栅栏式Exchange,是一种两方栅栏
任务执行
Executor框架
Executor exec = new Executors.newFixedThreadPool(n);
exec.execute();
- 静态工厂方法
- newFixedThreadPool:固定长度
- newCachedThreadPool:可缓存,规模不存在任何限制
- newSingleThreadExecutor:单线程,确保工作顺序执行
- newScheduledThreadPool:固定长度,以延时或定时的方式来执行任务,类似于Timer
- 生命周期
- shutdown:不接受新的任务,等待已经提交的任务执行完成(包括未开始执行的任务)
- shutdownNow:直接关闭所有任务
- awaitTermination:等待ExecutorService到达终止状态
- isTerminated:查看是否终止
寻找可利用的并行性
- 携带结果的任务Callable与Future
Future的get中如果抛出了异常,会封装为ExecutionException并重新抛出,可以通过getCause获取被包装的异常。ExecutorService的submit方法将发挥一个Future - CompletionService:Exector与BlockingQueue
CompletionService将Executor和BlockingQueue的功能融合在一起,可以将Callable任务提交执行,然后使用take、poll等方法获取结果,结果封装为Future。ExecutorCompletionService实现了CompletionService,并将计算部分委托给一个Executor。
ExecutorCompletionService在构造函数中创建一个BlockingQueue来保存计算完成的结果,当计算完成时,调用Future-Task中的done方法。提交任务时,首先将任务包装为一个QueueingFuture(FutureTask的一个子类),然后改写子类的done方法,并将结果放入BlockingQueue。
取消与关闭
任务取消
- 使用volatile类型的域来保存取消状态
- 中断是实现取消的最合理方式
- 3.