多线程之DownCountLatch CyclicBarrier和Semaphore

来源:互联网 发布:plc编程梯形图简单实例 编辑:程序博客网 时间:2024/06/05 21:52

一.概述

          DownCountLatch ,CyclicBarrier和Semaphore都是共享锁,但是他们达到的效果不一样

          DownCountLatch :DownCountLatch 让一个线程等待,等其他线程运行某一个条件后,这个线程才可以继续运行。DownCountLatch在实例话的时候可以传这个int类型的数据count,count是锁计数器,只有当count等于0的时候,等待的线程才能运行下去。当一个线程调用DownCountLatch的await方法的时候,这个线程会处于等待状态,要想让这个线程拿到共享锁继续运行下去,就得让其他线程调用countDown方法,每个线程调用countDown方法一次,count就会减一,当count减到0为止,这个线程才会继续运行下去。

         CyclicBarrier:CyclicBarrier是让N个线程相互等下去。在实例化CyclicBarrier的时候会给它传一个int类型的参数N,只有N个线程都运行到CyclicBarrier的await方法的时候,这些线程才能继续运行下去。也就是说当前面N-1个线程运行到await方法的时候,N-1个线程都是等待的状态,只有当第N个线程运行await方法的时候,这N个线程才是处于就绪状态。

        Semaphore:在实例化Semaphore的时候,会传一个int类型的参数count,count就代表着Semaphore的信号池中有Semaphore个信号量,当一个线程调用Semaphore的acquire()或acquire(n)方法的时候就是获取1个或n个信号量,Semaphore的信号池就会减去这个线程获取到的信号量,当其他线程再调用acquire(m)方法获取信号量的时候,Semaphore信号池的中的信号量个数大于m,这个线程就可以继续运行,当信号池中的信号量小于m,这个线程就会处于等待状态,等待拥有信号量的线程调用release(n)方法释放自己所拥有的的信号,等信号池的信号量大于等于索要的信号量时,这个线程才会继续运行下去。

二.举例

1.DownCountLatch举例说明            

package wangbiao.test.runnable;import java.util.concurrent.CountDownLatch;/**  * 共享锁CountDownLatch举例 * @author  作者 wangbiao * @date 创建时间:2017年6月12日 下午6:21:28  * @parameter  * @return  */public class CountDownLatchTest {public static void main(String[] args) throws InterruptedException{CountDownLatch countDownLatch = new CountDownLatch(5);System.out.println(Thread.currentThread().getName()+"   start");for(int i=0;i<5;i++){RunnableDemo runnableDemo = new RunnableDemo(countDownLatch);Thread thread = new Thread(runnableDemo,i+"");thread.start();}countDownLatch.await();System.out.println(Thread.currentThread().getName()+"   end");}  }class RunnableDemo implements Runnable{CountDownLatch countDownLatch;public RunnableDemo(CountDownLatch countDownLatch){this.countDownLatch = countDownLatch;}@Overridepublic void run(){try {Thread.sleep(2000);System.out.println(Thread.currentThread().getName()+"========start");countDownLatch.countDown();} catch (InterruptedException e) {e.printStackTrace();}}}
运行结果:

main   start2========start0========start4========start1========start3========startmain   end
main线程在运行到21行的countDownLatch.await()代码时会处于等待状态,其他的五个线程即使在运行过程中都暂停了2秒,但main线程还是等其他五个线程都调用了countDownLatch的countDown()方法后,main线程才继续运行下去。


2.cyclicBarrier举例说明

package wangbiao.test.runnable;import java.util.concurrent.CountDownLatch;import java.util.concurrent.CyclicBarrier;/**  * @author  作者 wangbiao * @date 创建时间:2017年6月12日 下午8:06:18  * @parameter  * @return  */public class CyclicBarrierTest {public static void main(String[] args) throws Exception{CyclicBarrier cyclicBarrier = new CyclicBarrier(5,new Runnable(){public void run(){System.out.println("cyclicBarrier 触发的事件");}});for(int i=0;i<5;i++){RunnableDemoTwo runnableDemoTwo = new RunnableDemoTwo(cyclicBarrier);Thread thread = new Thread(runnableDemoTwo,i+"");thread.start();}}  }class RunnableDemoTwo implements Runnable{CyclicBarrier cyclicBarrier;public RunnableDemoTwo(CyclicBarrier cyclicBarrier){this.cyclicBarrier = cyclicBarrier;}@Overridepublic void run(){try {Thread.sleep(5000);System.out.println(Thread.currentThread().getName()+"========start");cyclicBarrier.await();System.out.println(Thread.currentThread().getName()+"========end");} catch (Exception e) {e.printStackTrace();}}}
运行结果:

3========start4========start0========start2========start1========startcyclicBarrier 触发的事件1========end3========end0========end4========end2========end
当线程0,1,2,3,4中的前3个线程运行到41行cyclicBarrier的await()方法的时候,这3个线程都是处于等待状态的,当第4个线程运行完await()方法的时候,会触发cyclicBarrier中的预置线程,然后这四个线程就是进入就绪状态去竞争cpu然后运行下去。当然也可以不用设置cyclicBarrier的预置线程,那这四个线程就直接是就绪状态了。


3.Semaphore举例说明

package wangbiao.test.runnable;import java.util.concurrent.CyclicBarrier;import java.util.concurrent.Semaphore;/**  * @author  作者 wangbiao * @date 创建时间:2017年6月12日 下午8:33:39  * @parameter  * @return  */public class SemaphoreTest {public static void main(String[] args){Semaphore semaphore = new Semaphore(10);RunnableDemoThree runnableDemoThree1 = new RunnableDemoThree(semaphore,5);RunnableDemoThree runnableDemoThree2 = new RunnableDemoThree(semaphore,3);RunnableDemoThree runnableDemoThree3 = new RunnableDemoThree(semaphore,7);Thread thread1 = new Thread(runnableDemoThree1,1+"");Thread thread2 = new Thread(runnableDemoThree2,2+"");Thread thread3 = new Thread(runnableDemoThree3,3+"");thread1.start();thread2.start();thread3.start();} }class RunnableDemoThree implements Runnable{Semaphore semaphore;int i;public RunnableDemoThree(Semaphore semaphore,int i){this.semaphore = semaphore;this.i = i;}@Overridepublic void run(){try {semaphore.acquire(i);Thread.sleep(2000);System.out.println(Thread.currentThread().getName()+"========end");} catch (Exception e) {e.printStackTrace();}finally {             // 释放给定数目的许可,将其返回到信号量。semaphore.release(i);System.out.println(Thread.currentThread().getName()+"========i:"+i);    }}}
运行结果:

2========end1========end2========i:31========i:53========end3========i:7
线程1,2,3运行到第40行的semaphore.acquire(i)方法的时候,semaphore信号池的信号量是10,线程1和线程2分别获取了5个和3个信号量,线程池的限号量还剩2个,等线程3再去获取7个信号量的时候就会处于等待状态,线程3只有等待线程1和线程2运行到47行的semaphore.release(i)时,线程3才能获取到足够的信号量,才能继续运行下去。


以上是我对CountDownLatch,CyclicBarrier和Semaphore这个共享锁最基本的理解,希望能帮到你。如果你想更深入的去理解这几个共享锁的原理,可以看看下面的链接

参考链接:

http://www.cnblogs.com/skywang12345/p/3533887.html

http://www.cnblogs.com/skywang12345/p/3533995.html

http://www.cnblogs.com/skywang12345/p/3534050.html



阅读全文
0 0
原创粉丝点击