Java5的java.util.concurrent包下引入了大量的用于解决并发问题的新类;相对于前面那些基础的线程同步和通信的方法,这些新类是一种更高层次上的抽象,使用起来还是比较容易的.这篇博客就来学习其中的两个新类:CountDownLatch和CyclicBarrier;并使用CyclicBarrier来模拟一个简单的赛马游戏.
一.CountDownLatch
使用CountDownLatch对象时,我们需要给其设定一个初始的计数值,然后在这个对象上调用await()的任务都会阻塞,直到这个对象的计数值减为0;其它的任务可以在完成自己的工作时调用这个对象的countDown()方法来减少这个对象的计数值。所以这个类可以用于同步一个或多个任务,强制它们等待由其它任务执行的一组操作完成;一个典型的应用场景是将一个程序分解为n个互相独立的可解决任务,并创建值为n的CountDownLatch,当每个任务完成时,就会在这个对象上调用countDown().而那些等待这个问题被解决的任务在这个对象上调用await(),使自己阻塞,直到这个对象计数值减为0;另外值得注意的一点是这个对象并不会协调n个任务执行的先后顺序。下面演示这种技术的一个框架示例:
package lkl;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/** * CountDownLatch用来同步一个或多个任务,强制它们 * 等待由其它任务执行的一组操作完成 * */
//预先执行的任务
class TaskPortion implements Runnable{
private static int counter = 0;
private final int id= counter++;
//全局多个线程共享一个Random对象,这里其实牵涉到一个并发问题
//只是实际上Random.next()本身就是线程安全的,所以不需要我们自己进行同步
private static Random rand = new Random(47);
private final CountDownLatch latch;
public TaskPortion(CountDownLatch latch){
this.latch = latch;
}
public void run(){
try{
dowork();
latch.countDown(); //减少计数值