CountDownLatch、CyclicBarrier和Semaphore的简单介绍和坑

CountDownLatch

count初始化CountDownLatch,然后需要等待的线程调用await方法。await方法会一直受阻塞直到count=0。而其它线程完成自己的操作后,调用countDown()使计数器count减1。当count减到0时,所有在等待的线程均会被释放
说白了就是通过count变量来控制等待,如果count值为0了(其他线程的任务都完成了),那就可以继续执行。

public class CountDownLatchTest {

    public static void main(String[] args) {
    final   CountDownLatch countDownLatch = new CountDownLatch(5);
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                try {
                    //在countDownLathch为0之前,用await()都会阻塞该线程。
                    countDownLatch.await();
                System.out.println(Thread.currentThread().getId()+"终于能运行啦");
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                
            }
        }).start();
        
        for(int i=0;i<5;i++) {
            new Thread(new Runnable() {
                
                @Override
                public void run() {
                    countDownLatch.countDown();
                    System.out.println(Thread.currentThread().getId()+"执行countDown()操作,此时countDownLatch值为"+countDownLatch);
                    
                }
            }).start();
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
    }
}

输出结果:

image.png

CyclicBarrier

CountDownLatch注重的是等待其他线程完成,CyclicBarrier注重的是:当线程到达某个状态后,暂停下来等待其他线程,所有线程均到达以后,继续执行。

public class CyclicBarrierTest {
    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(2);

        for (int i = 0; i < 2; i++) {
            new Thread(new Runnable() {

                @Override
                public void run() {
                    try {
                        cyclicBarrier.await();
                        System.out.println("线程" + Thread.currentThread().getName() + "准备好啦");
                        cyclicBarrier.await();
                        System.out.println("线程" + Thread.currentThread().getName() + "登录了游戏");
                        cyclicBarrier.await();
                        System.out.println("线程" + Thread.currentThread().getName() + "打游戏咯");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }

    }

}

输出结果

image.png

Semaphore

Semaphore(信号量)实际上就是可以控制同时访问的线程个数,它维护了一组"许可证"
当调用acquire()方法时,会消费一个许可证。如果没有许可证了,会阻塞起来
当调用release()方法时,会添加一个许可证。
这些"许可证"的个数其实就是一个count变量罢了~

特别注意的点!!!
当Semaphore的值设为0的时候,此时调用acquire()会阻塞当前线程,而如果先调用release()再调用acquire(),即可运行。(很重要,)

public class SemaphoreTest {

    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(5);
        for (int i = 0; i < 20; i++) {
            new Thread(new Runnable() {

                @Override
                public void run() {
                    try {
                        semaphore.acquire();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "拿到通行证咯");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "归还通行证");
                    semaphore.release();

                }
            }).start();
        }
    }
}

输出描述:

image.png

你可能感兴趣的:(CountDownLatch、CyclicBarrier和Semaphore的简单介绍和坑)