java并发学习之CountDownLatch
2013-12-29 00:00
603 查看
摘要: 用CountDownLatch编写健壮的并发程序。
从java se5开始,java.util.concurrent中就引入了大量设计用来解决并发问题的新类。学习使用这些新类有助于我们编写出更加简单而健壮的并发程序。
今天我们开始学习第一个类:CountDownLatch
他被用来同步一个或多个任务,强制他们等待其他任务执行完毕。
countdownlatch中有一个初始计数值,任何在countdown对象上调用await()方法的任务都将被阻塞,直到初始计数值为0.用来改变初始计数值数值的方法是countdown(),每调用一次,初始值就会减一。这个方法多调用不会引起崩溃和异常,即当调的次数大于初始计数值时,latch.getCount()得到的值都为0。
countdownlatch被设计为只触发一次,计数值不能被重置。我理解是只适用于业务逻辑可以简单地分为两个阶段的情况。比如说,A:所有政治局常委到场,B:开会. A和B的顺序是不能调的。但是A里面哪个常委先到,B里面哪项议程先说,这个都是不重要的。
下面是一个例子。
从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(); { } } }