android 简单线程同步之CountDownLatch

maplele 2011-12-30

推荐安卓开发神器(里面有各种UI特效和android代码库实例)

当涉及到多线程的时候,一个经常出现的问题就是线程同步,这里介绍android一个很简单的多线程同步方案-------------CountDownLatch

我们直接看官方例子。这个例子有两个功能,

1.N个子线程等待主线程进行一些初始化工作doSomethingInit()之后,才运行子线程

2.主线程等待N个子线程都结束之后才继续做其它的事情。

classDriver{// ...

   voidmain()throwsInterruptedException{

     CountDownLatchstartSignal=newCountDownLatch(1);

     CountDownLatchdoneSignal=newCountDownLatch(N);

     for(inti=0;i<N;++i)// create and start threads

       newThread(newWorker(startSignal,doneSignal)).start();

     doSomethingInit();           // 做初始化工作

     startSignal.countDown();     // 让所有子线程运行

     doneSignal.await();         // 等待所有子线程结束 

doSomethingElse();             //做其它事情。

   }

 }

 classWorkerimplementsRunnable{

   privatefinalCountDownLatchstartSignal;

   privatefinalCountDownLatchdoneSignal;

   Worker(CountDownLatchstartSignal,CountDownLatchdoneSignal){

     this.startSignal=startSignal;

     this.doneSignal=doneSignal;

   }

   publicvoidrun(){

     try{

        startSignal.await();

        doWork();

        doneSignal.countDown();

     }catch(InterruptedExceptionex){}// return;

   }

   voiddoWork(){...}

 }

CountDownLatch类只有一个成员变量,就是一个整形值,是个计数器,而且成员函数也只有两个经常调用的函数。

1.countDown,让计数器减去

2.await。等待计数器为0,然后继续从await后面运行。

原理就是这样,我们来看代码。

 CountDownLatchstartSignal=newCountDownLatch(1);

 CountDownLatchdoneSignal=newCountDownLatch(N);

 for(inti=0;i<N;++i)// create and start threads

       newThread(newWorker(startSignal,doneSignal)).start();

这里主线程开启了N个线程,并调用了start函数,同时传入两个用于同步的CountDownLatch,我们看线程里面有

startSignal.await();

 doWork();

doneSignal.countDown();

什么意思呢?就是startSignal.await()让该线程等待,直到startSignal里面的计数器为0才开始运行,那他什么时候为0呢?我们在看到主线程有

 doSomethingInit();           // 做初始化工作

 startSignal.countDown();     // 让所有子线程运行

startSignal是在主线程做了doSomethingInit()这个函数之后,调用 startSignal.countDown()让startSignal的计数器减1,我们看startSignal的计数器初始值是多少,

CountDownLatchstartSignal=newCountDownLatch(1);

不错,是1,也就是,只要主线程一执行startSignal.countDown(),startSignal的计数就马上变成0,所有子线程就运行起来了,因为所有的子线程都在等startSignal它变成0。

当所有子线程都运行起来之后,我们来看现在主线才执行到哪儿了:

doneSignal.await();         // 等待所有子线程结束 

不错,主线程又在等在中,等待doneSignal的计数器变成0,我们再来看doneSignal的初始值是多少

 CountDownLatchdoneSignal=newCountDownLatch(N);

是N,也就是说要执行N次的doneSignal.countDown,主线程才能继续运行,我们来看doneSignal的计数器在那里减少的,看到子线程里面

 doWork();

doneSignal.countDown();

子线程在执行了doWork()之后,就会doneSignal.countDown();让doneSignal的计数器减1,一个子线程自会执行一次doneSignal.countDown();但是N个子线程就执行了N次doneSignal.countDown();所以当所有子线程都执行过doneSignal.countDown();之后,doneSignal的计数器就变成0了,然后主线程就可以继续运行了。

做其它的事情。

doSomethingElse();             //做其它事情。

相关推荐