CountDownLatch与CyclicBarrier区别以及CountDownLatch用法示例Demo

 

CountDownLatch能够实现等待多个独立的线程执行结束后再继续执行主线程操作。与CyclicBarrier类似。不过也有区别。
CountDownLatch与CyclicBarrier最大区别是应用场景和计数器可否循环使用。

1.应用场景不同:

CountDownLatch的应用场景:某个线程执行前等待多个线程执行结束

CyclicBarrier的应用场景:一组线程之间互相等待。

2.可否循环使用不同:

CountDownLatch不可循环使用,一旦减到0,再有线程调用await()方法会直接通过。

CyclicBarrier可以循环使用,减到0后自动重置为你设定的初始值。

 

这里是CountDownLatch的Demo。CyclicBarrier的Demo参考上一篇:CyclicBarrier的使用示例Demo

CountDownLatchTest.java

package com.example.demo.concurrent.countdownlatch;

import lombok.extern.slf4j.Slf4j;

import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Slf4j
public class CountDownLatchTest {
    public static void main(String[] args) {
        CountDownLatch latch = new CountDownLatch(2);
        ThreadA threadA = new ThreadA(latch);
        ThreadB threadB = new ThreadB(latch);
        threadA.start();
        threadB.start();

        try {
            log.info("主线程开始等待-----------");
            latch.await();
            log.info("主线程停止等待----两个线程都执行完了-----");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("主线程执行结束------");
    }
}

ThreadA.java 

package com.example.demo.concurrent.countdownlatch;

import lombok.extern.slf4j.Slf4j;

import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

@Slf4j
public class ThreadA extends Thread {
    private CountDownLatch latch;
    public ThreadA(CountDownLatch countDownLatch) {
        latch = countDownLatch;
    }

    @Override
    public void run() {
        log.info("执行线程A-----开始----");
        try {
            TimeUnit.SECONDS.sleep(new Random().nextInt(5));
            log.info("执行线程A-----结束----");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            latch.countDown();
        }
    }
}

 ThreadA与ThreadB代码一样,名字不同而已。

 

执行结果为:

Connected to the target VM, address: '127.0.0.1:51936', transport: 'socket'
00:31:23.075 [main] INFO com.example.demo.concurrent.countdownlatch.CountDownLatchTest - 主线程开始等待-----------
00:31:23.075 [Thread-1] INFO com.example.demo.concurrent.countdownlatch.ThreadB - 执行线程B-----开始----
00:31:23.075 [Thread-0] INFO com.example.demo.concurrent.countdownlatch.ThreadA - 执行线程A-----开始----
00:31:24.086 [Thread-0] INFO com.example.demo.concurrent.countdownlatch.ThreadA - 执行线程A-----结束----
00:31:28.086 [Thread-1] INFO com.example.demo.concurrent.countdownlatch.ThreadB - 执行线程B-----结束----
00:31:28.086 [main] INFO com.example.demo.concurrent.countdownlatch.CountDownLatchTest - 主线程停止等待----两个线程都执行完了-----
00:31:28.086 [main] INFO com.example.demo.concurrent.countdownlatch.CountDownLatchTest - 主线程执行结束------
Disconnected from the target VM, address: '127.0.0.1:51936', transport: 'socket'

主线程在等待线程A和线程B,当线程A和线程B都执行结束后,主线程才开始继续执行。

主线程latch.await()的作用是等待使用了latch这个对象的两个线程执行结束。

子线程的使用方式是finally模块中添加latch.countDown()


PS:找到一个赛跑的Demo:CountDownLatch的理解和使用

package com.example.demo.concurrent.countdownlatch;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CountDownLatchTest2 {
    public static void main(String[] args) {
        ExecutorService service = Executors.newCachedThreadPool();
        final CountDownLatch cdOrder = new CountDownLatch(1);
        final CountDownLatch cdAnswer = new CountDownLatch(4);
        for (int i = 0; i < 4; i++) {
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println("选手" + Thread.currentThread().getName() + "正在等待裁判发布口令");
                        cdOrder.await();
                        System.out.println("选手" + Thread.currentThread().getName() + "已接受裁判口令");
                        Thread.sleep((long) (Math.random() * 10000));
                        System.out.println("选手" + Thread.currentThread().getName() + "到达终点");
                        cdAnswer.countDown();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            service.execute(runnable);
        }
        try {
            Thread.sleep((long) (Math.random() * 10000));
            System.out.println("裁判"+Thread.currentThread().getName()+"即将发布口令");
            cdOrder.countDown();
            System.out.println("裁判"+Thread.currentThread().getName()+"已发送口令,正在等待所有选手到达终点");
            cdAnswer.await();
            System.out.println("所有选手都到达终点");
            System.out.println("裁判"+Thread.currentThread().getName()+"汇总成绩排名");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        service.shutdown();
    }
}

执行结果是:

选手pool-1-thread-2正在等待裁判发布口令
选手pool-1-thread-3正在等待裁判发布口令
选手pool-1-thread-4正在等待裁判发布口令
选手pool-1-thread-1正在等待裁判发布口令
裁判main即将发布口令
裁判main已发送口令,正在等待所有选手到达终点
选手pool-1-thread-2已接受裁判口令
选手pool-1-thread-1已接受裁判口令
选手pool-1-thread-4已接受裁判口令
选手pool-1-thread-3已接受裁判口令
选手pool-1-thread-1到达终点
选手pool-1-thread-4到达终点
选手pool-1-thread-3到达终点
选手pool-1-thread-2到达终点
所有选手都到达终点
裁判main汇总成绩排名

 

你可能感兴趣的:(Java,多线程)