从java se5开始,java.util.concurrent中就引入了大量设计用来解决并发问题的新类。学习使用这些新类有助于我们编写出更加简单而健壮的并发程序。
今天我们开始学习第一个类:CountDownLatch
他被用来同步一个或多个任务,强制他们等待其他任务执行完毕。
countdownlatch中有一个初始计数值,任何在countdown对象上调用await()方法的任务都将被阻塞,直到初始计数值为0.用来改变初始计数值数值的方法是countdown(),每调用一次,初始值就会减一。这个方法多调用不会引起崩溃和异常,即当调的次数大于初始计数值时,latch.getCount()得到的值都为0。
countdownlatch被设计为只触发一次,计数值不能被重置。我理解是只适用于业务逻辑可以简单地分为两个阶段的情况。比如说,A:所有政治局常委到场,B:开会. A和B的顺序是不能调的。但是A里面哪个常委先到,B里面哪项议程先说,这个都是不重要的。
下面是一个例子。
/**
* 新类库中的组件
*/
package hyf.concurrent.newLibWidget;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* @author haoyifeng
*
*/
class TaskPortrain implements Runnable
{
private static int counter = 0;
private final int id = counter++;
private static Random rand = new Random(47);
private final CountDownLatch latch;
public TaskPortrain(CountDownLatch latch)
{
this.latch = latch;
}
@Override
public void run()
{
doWork();
latch.countDown();
}
public void doWork()
{
try
{
TimeUnit.MILLISECONDS.sleep(rand.nextInt(1000));
System.out.println("latch count is "+latch.getCount());
System.out.println(this+"completed.");
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
public String toString()
{
// return String.format("%1$-3d", id);
return id+" ";
}
}
class TaskWaiting implements Runnable
{
private static int counter = 0;
private final int id = counter++;
private final CountDownLatch latch;
public TaskWaiting(CountDownLatch latch)
{
this.latch = latch;
}
@Override
public void run()
{
try
{
latch.await();
// latch.wait(); //notify(), notifyAll(),wait(), wait(long), wait(long, int)对应的锁是synchronized.与countdownlatch不是一个东西。
System.out.println("latch barrier passed for "+this);
} catch (InterruptedException e)
{
e.printStackTrace();
System.out.println(this+" interrupted.");
}
}
@Override
public String toString()
{
return String.format("TaskWaiting %1$-3d", id);
}
}
public class CountDownLatchTest1
{
static int SIZE = 100;
/**
* @param args
*/
public static void main(String[] args) throws Exception
{
ExecutorService exec = Executors.newCachedThreadPool();
CountDownLatch latch = new CountDownLatch(SIZE);
for(int i=0;i<10;i++)
exec.execute(new TaskWaiting(latch));
for (int i = 0; i < SIZE; i++)
// for (int i = 0; i < SIZE+100; i++)
exec.execute(new TaskPortrain(latch));
// new TaskPortrain(latch).run();
System.out.println("all tasks latched. ");
exec.shutdown();
{
}
}
}