`
jimichan
  • 浏览: 277942 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Concurrent In Java 6 分享,第四部分 同步辅助类介绍

    博客分类:
  • java
阅读更多

第一部分 集合 http://jimichan.iteye.com/blog/951948

 

第二部分 线程池 http://jimichan.iteye.com/blog/951950

 

第三部分 锁 http://jimichan.iteye.com/blog/951954

 

第四部分 同步辅助类 http://jimichan.iteye.com/blog/951955

Concurrent In Java,第四部分 同步辅助类

 

2011-3-9  延昭 & 陈汝烨 版权所有,特别禁止发布到百度文库

这篇是来自公司内部分享会议是写的总结,有些内容没有表达出来,大家可以来踩,但是需留下原因,以便后续补充。

4. 同步辅助类

你提交了一些任务,但你想等它们都完成了再做另外一些事情;你提交了一些任务,但是不想让它们立刻执行,等你喊123开始的时候,它们才开始执行;等等这些场景,线程之间需要相互配合,或者等待某一个条件成熟执行。这些场景想你就需要用到同步辅助类。

 

4.1 CountDownLatch

 

CountDownLatch 内部有个计数器,通过构造函数来指定。这个类就好比是倒计时的电子牌,当倒计时为0的时候就可以一起做一些事情。

 

摘自JavaDoc的方法介绍

void

await()

         使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断

boolean

await(long timeout, TimeUnit unit)

         使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间。

void

countDown()

         递减锁存器的计数,如果计数到达零,则释放所有等待的线程。

long

getCount()

         返回当前计数。

 

 

摘自JavaDoc的例子

 

class Driver { // ...
  void main() throws InterruptedException {
    CountDownLatch startSignal = new CountDownLatch(1);
    CountDownLatch doneSignal = new CountDownLatch(N);

    for (int i = 0; i < N; ++i) // create and start threads
      new Thread(new Worker(startSignal, doneSignal)).start();

    doSomethingElse();            // don't let run yet
    startSignal.countDown();      // let all threads proceed
    doSomethingElse();
    doneSignal.await();           // wait for all to finish
  }
}

class Worker implements Runnable {
  private final CountDownLatch startSignal;
  private final CountDownLatch doneSignal;
  Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
     this.startSignal = startSignal;
     this.doneSignal = doneSignal;
  }
  public void run() {
     try {
       startSignal.await();
       doWork();
       doneSignal.countDown();
} catch (InterruptedException ex) {} // return;
  }

  void doWork() { ... }
}

 

当CountDownLatch(1)的时候,它就好比是个信号枪了。

 

4.2 CyclicBarrier

 

这个同步辅助类,它让多个线程可以在多个屏障点进行等待,所以叫cyclic,而且有个附加选择你可以在线程到达屏障点后执行一个任务(在释放其他线程之前)

new CyclicBarrier(N, 
                                new Runnable() {
                                  public void run() { 
                                    mergeRows(...); 
                                  }
});

 

为了帮助你理解,假设一个场景。

 

有一个任务,A、B、C分别从三个仓库(甲乙丙)搬运不同3个不同的零件到客户X的公司,然后再一起组装机器,完成后一起坐车去公司总部。

 

这个任务需要ABC三个线程同时进行,但是由于从仓库到客户X那边距离不等、交通状态未知的情况下,所花费的时间也不等。同时由于三个人负责的零件不同,所以安装机器的时候花费时间也不一样。这个场景中有两个需要线程间等待的地方。CyclicBarrier就可以闪亮登场了。

 

public class Main3 {

        public static void main(String[] args) {

                

                CyclicBarrier barrier = new CyclicBarrier(3,new Runnable() {

                        

                        @Override

                        public void run() {

                                System.out.println("到达公共屏障点");                                

                        }

                });

                

                ExecutorService es = Executors.newCachedThreadPool();

                

                es.submit(new Worker("A", 5000, 8000, barrier));

                es.submit(new Worker("B", 2000, 16000, barrier));

                es.submit(new Worker("C", 9000, 2000, barrier));

                

                es.shutdown();

        }

 

        static class Worker implements Runnable {

                String name;

                int t1;// 搬运零件所需要的时间

                int t2;// 参与组装工作需要的时间

 

                CyclicBarrier barrier;

 

                public Worker(String name, int t1, int t2, CyclicBarrier barrier) {

                        super();

                        this.name = name;

                        this.t1 = t1;

                        this.t2 = t2;

 

                        this.barrier = barrier;

                }

 

                @Override

                public void run() {

                        try {

                                print(name + " 开始搬运零件");

 

                                Thread.sleep(t1);// 模拟搬运时间

 

                                print(name + " 到达目的地");

 

                                int a = barrier.await(); // 等待其他人

                                if(a==0){

                                        //说明是最后一个到的可以执行特殊操作

                                }

                                

                                

                                print(name + " 开始组装机器");

                                

                                Thread.sleep(t2);// 模拟组装时间.

                                print(name + " 完成组装机器");

                                

                                barrier.await(); // 等待其他人组装完毕

                                

                                print(name + " 一起回总公司");

 

                        } catch (Exception e) {

                                e.printStackTrace();

                        }

 

                }

 

        }

        

        static SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");  

        static void print(String x) {  

       System.out.println( sdf.format(new Date()) + ": "+x);

   }  

}

 

4.3 Semaphore

 

一个经典的信号量计数器。一般被用来控制对共享资源同时访问线程数量的控制。

 

特殊情况下信号量设置为1,那么就类似互斥锁的功能。

 

此类的构造方法可选地接受一个公平 参数。当设置为 false 时,此类不对线程获取锁的顺序做任何保证。和之前提到的争用获取顺序一样,在非公平模式下,系统将获得更好的吞吐量,jvm也会保证在非公平模式下让所有线程得到访问机会。

 

 

参考书目

 

JavaDoc http://www.oschina.net/uploads/doc/javase-6-doc-api-zh_CN/overview-summary.html

 

java.util.concurrent 您不知道的 5 件事

http://www.ibm.com/developerworks/cn/java/j-5things4.html?ca=drs-

http://www.ibm.com/developerworks/cn/java/j-5things15/index.html

 

0
1
分享到:
评论
1 楼 peak 2011-03-12  
不错

相关推荐

Global site tag (gtag.js) - Google Analytics