maplele 2011-12-30
当涉及到多线程的时候,一个经常出现的问题就是线程同步,这里介绍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(); //做其它事情。 |