CountDownLatch使用

分享牛原创,CountDownLatch类的使用,CountDownLatch是一个工具类,运行主线程开启子线程的时候,子线程还没有结束的时候,主线程可以一直等待,直到初始化的现成的计数器count为0,主线程就可以不用等待继续执行了。count只能在实例化CountDownLatch类的时候初始化,没有其他的办法count注入值。

下面看一下java.util.concurrent.CountDownLatch如何使用。

1.1.1. CountDownLatch类中的方法

CountDownLatch类中的主要访法如下图所示:

构造方法如下所示:

public CountDownLatch(int count) {

if (count < 0) throw new IllegalArgumentException("count < 0");

this.sync = new Sync(count);

}

在这里要特别注意,实例化CountDownLatch类的时候,参数值一定要与启动的线程个数一直。假如启动三个线程,我们这里传入的值是4,那么每个线程结束的时候调用countDown方法的时候,计数器会减去1,这样三个完成之后,计数器时1,则程序就是一直等待状态。永远不会向下执行。

countDown方法,当前线程调用此方法,则计数在实例化CountDownLatch中传入的值基础上减一。

awaint方法,调用此方法会一直阻塞当前线程,不会向下执行,直到计时器的值为0的时候程序才会继续向下执行。

1.1.2. 测试

下面的程序开始测试CountDownLatch的使用。

package com.shareniu.zkTest;

import java.util.concurrent.CountDownLatch;
public class ShareniuDriver {

private static final int N = 2;

public static void main(String[] args) throws InterruptedException {
CountDownLatch doneSignal = new CountDownLatch(N);
for (int i = 0; i < N; ++i) // create and start threads
{
new Thread(new Worker(doneSignal,i)).start();
}
doneSignal.await();
doSomethingElse(); // don‘t let run yet
}
private static void doSomethingElse() {
System.out.println("分享牛 我在做其他事情.....");
}
static class Worker implements Runnable {
private CountDownLatch doneSignal;
private int i;
public Worker( CountDownLatch doneSignal,int i) {
this.doneSignal = doneSignal;
this.i=i;
}
public void run() {
try {
doWork();
} catch (Exception e) {

} finally {
doneSignal.countDown();
}
}
private void doWork() {
System.out.println("开始工作....."+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

上面的程序可以得出一个结论:count为0的时候,await()之后的方法才会去执行,否则一直处于等待状态。

上面的是启动2个线程,当我们把N设置为3的时候,也就是大于2的任意数的时候,启动2个线程,其他地方不变化,发现程序一直等待,不执行。这个也间接说明了,只有count为0的时候,程序才会继续走下去。

1.1.3. 工作原理

工作原理如下图所示:

1.1.4. 使用场景

程序启动的时候,根据业务开启几个线程去执行检查服务是否正常,主线程一直等待,当检查的线程都结束的时候,主线程才能去判断对应的所有的线程返回结果,检查是否正常。

比如有一个任务A,它要等待其他4个任务执行完毕之后才能执行,此时就可以利用CountDownLatch来实现这种功能了。

具体的程序如下:

1.1.4.1. BaseHealthChecker 类,所有类的基类

package com.shareniu.zkTest;
import java.util.concurrent.CountDownLatch;
public abstract class BaseHealthChecker implements Runnable {
private CountDownLatch latch;
private String serviceName;
private boolean serviceUp;

public BaseHealthChecker(CountDownLatch latch, String serviceName) {
this.latch = latch;
this.serviceName = serviceName;
}
public void run() {
try {
verifyService();
            serviceUp = true;
} catch (Exception e) {
 e.printStackTrace(System.err);
            serviceUp = false;
}finally{
if(latch != null) {
                latch.countDown();
            }
}
}
public abstract void verifyService();
public CountDownLatch getLatch() {
return latch;
}
public String getServiceName() {
return serviceName;
}
public boolean isServiceUp() {
return serviceUp;
}
}

1.1.4.2. NetworkHealthChecker 类

package com.shareniu.zkTest;

import java.util.concurrent.CountDownLatch;

public class NetworkHealthChecker extends BaseHealthChecker {

public NetworkHealthChecker(CountDownLatch latch, String serviceName) {
super(latch, serviceName);
}

@Override
public void verifyService() {
System.out.println("开始检查 " + this.getServiceName());
        try
        {
            Thread.sleep(7000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        System.out.println(this.getServiceName() + " 检查结束");
}

}

1.1.4.3. CacheHealthChecker 类

package com.shareniu.zkTest;

import java.util.concurrent.CountDownLatch;

public class CacheHealthChecker extends BaseHealthChecker {

public CacheHealthChecker(CountDownLatch latch, String serviceName) {
super(latch, serviceName);
}

@Override
public void verifyService() {
System.out.println("开始检查  CacheHealthChecker" + this.getServiceName());
        try
        {
            Thread.sleep(2000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        System.out.println(this.getServiceName() + "CacheHealthChecker 检查结束 ");
}

}

1.1.4.4. 测试类

package com.shareniu.zkTest;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class AppTest {
 private static List<BaseHealthChecker> services;
    private static CountDownLatch latch;
public static void main(String[] args) throws InterruptedException {
 latch = new CountDownLatch(2);
 services=new ArrayList<BaseHealthChecker>();
 services.add(new CacheHealthChecker(latch, "CacheHealthChecker"));
 services.add(new NetworkHealthChecker(latch, "NetworkHealthChecker"));
 ExecutorService executor  = Executors.newFixedThreadPool(services.size());
 for(final BaseHealthChecker v : services)
        {
            executor.execute(v);
        }
 //等待 指导所有的线程执行完毕
       latch.await();
       for(final BaseHealthChecker v : services)
        {
            boolean serviceUp = v.isServiceUp();
            System.out.println(v.getServiceName()+":"+serviceUp);
        }
}
}

运行结果如下所示:

开始检查  CacheHealthCheckerCacheHealthChecker

开始检查 NetworkHealthChecker

CacheHealthCheckerCacheHealthChecker 检查结束

NetworkHealthChecker 检查结束

CacheHealthChecker:true

NetworkHealthChecker:true

时间: 2024-10-10 14:12:51

CountDownLatch使用的相关文章

java多线程 -- CountDownLatch 闭锁

CountDownLatch 一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待.闭锁可以延迟线程的进度直到其到达终止状态,闭锁可以用来确保某些活动直到其他活动都完成才继续执行: 确保某个计算在其需要的所有资源都被初始化之后才继续执行; 确保某个服务在其依赖的所有其他服务都已经启动之后才启动; 等待直到某个操作所有参与者都准备就绪再继续执行. package com.company; import java.util.concurrent.CountDownLa

java计数器CountDownLatch

CountDownLatch里面有个属性为state,当为零时触发代码往下执行,代码如下: package threadLock; import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class CountDownLatchTest

【JAVA并发编程实战】4、CountDownLatch

这是一个计数锁,说白了,就是当你上锁的时候,只有计数减少到0的时候,才会释放锁 package cn.xf.cp.ch05; public class TaskRunable implements Runnable { @Override public void run() { System.out.println("do something..."); } public static void main(String []args) { Thread t = new Thread(n

CountDownLatch

CountDownLatch 1.类介绍 一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待.用给定的计数 初始化 CountDownLatch.由于调用了 countDown() 方法,所以在当前计数到达零之前,await 方法会一直受阻塞.之后,会释放所有等待的线程,await 的所有后续调用都将立即返回.这种现象只出现一次——计数无法被重置. 一个线程(或者多个), 等待另外N个线程完成某个事情之后才能执行 2.使用场景 在一些应用场合中,需要等待某个条件

Java Concurrency - 浅析 CountDownLatch 的用法

CountDownLatch 是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 用给定的计数初始化 CountDownLatch.由于调用了 countDown() 方法,所以在当前计数到达零之前,await 方法会一直受阻塞.之后,会释放所有等待的线程,await 的所有后续调用都将立即返回.这种现象只出现一次——计数无法被重置.如果需要重置计数,请考虑使用 CyclicBarrier. CountDownLatch 是一个通用同步工具,它有很多用途.将

浅析Java中CountDownLatch用法

/** CountDownLatch类是一个同步计数器,构造时传入int参数,该参数就是计数器的初始值,每调用一次countDown()方法,计数器减1,计数器大于0 时,await()方法会阻塞程序继续执行 CountDownLatch如其所写,是一个倒计数的锁存器,当计数减至0时触发特定的事件.利用这种特性,可以让主线程等待子线程的结束.下面以一个模拟运动员比赛的例子加以说明. */ import java.util.concurrent.CountDownLatch; import jav

java 线程 新类库中的构件 countDownLatch 使用

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGlhbmdydWkxOTg4/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" > package org.rui.thread.newc; import java.util.Random; import java.util.concurrent.CountDownLatch; import java.

CountDownLatch(闭锁)

一.闭锁(Latch)    闭锁(Latch):一种同步方法,可以延迟线程的进度直到线程到达某个终点状态.通俗的讲就是,一个闭锁相当于一扇大门,在大门打开之前所有线程都被阻断,一旦大门打开所有线程都将通过,但是一旦大门打开,所有线程都通过了,那么这个闭锁的状态就失效了,门的状态也就不能变了,只能是打开状态.也就是说闭锁的状态是一次性的,它确保在闭锁打开之前所有特定的活动都需要在闭锁打开之后才能完成. 应用场景: 1.确保某个计算在其需要的所有资源都被初始化之后才继续执行.二元闭锁(包括两个状态

Java 并发同步器之CountDownLatch、CyclicBarrier

一.简介 1.CountDownLatch是一个同步计数器,构造时传入int参数,该参数就是计数器的初始值,每调用一次countDown()方法,计数器减1,计数器大于0 时,await()方法会阻塞程序的执行. CountDownLatch可以看作是一个倒计数的锁存器,当计数减至0时触发特定的事件.利用这种特性,可以让主线程等待子线程的结束. CountDownLatch最重要的方法是countDown()和await(),前者主要是倒数一次,后者是等待倒数到0,如果没有到达0,就只有阻塞等待

深入浅出 Java Concurrency (10): 锁机制 part 5 闭锁 (CountDownLatch)[转]

此小节介绍几个与锁有关的有用工具. 闭锁(Latch) 闭锁(Latch):一种同步方法,可以延迟线程的进度直到线程到达某个终点状态.通俗的讲就是,一个闭锁相当于一扇大门,在大门打开之前所有线程都被阻断,一旦大门打开所有线程都将通过,但是一旦大门打开,所有线程都通过了,那么这个闭锁的状态就失效了,门的状态也就不能变了,只能是打开状态.也就是说闭锁的状态是一次性的,它确保在闭锁打开之前所有特定的活动都需要在闭锁打开之后才能完成. CountDownLatch是JDK 5+里面闭锁的一个实现,允许一