Java之CountDownLatch的用法(多线程协同工作)

Java (34) 2024-02-10 11:12

Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说Java之CountDownLatch的用法(多线程协同工作),希望能够帮助你!!!。

首先,我们在工作中会遇到这种场景,例如:我们需要执行多条任务,但是又想在任务都完成后,再返回给前端,或者做其他工作,因此我们需要用到CountDownLatch

  1. 我们创建一个业务类,来处理任务
@Component(value = "WorkService")
public class WorkService {

    public void work(String name) {
        System.out.println(name + "正在干活......");
    }

}

2.然后,创建一个工作类,去执行业务

public class Worker implements Runnable{

    private CountDownLatch downLatch;

    private String name;

    public Worker(CountDownLatch downLatch, String name){
        this.downLatch = downLatch;
        this.name = name;
    }

    @Override
    public void run() {

        this.doWork();

        try{
            TimeUnit.SECONDS.sleep(new Random().nextInt(10));
        }catch(InterruptedException ie){
        }

        System.out.println(this.name + "活干完了!");

        this.downLatch.countDown();

    }

    private void doWork(){

        WorkService service = SpringUtils.getBean("WorkService");

        service.work(this.name);

    }

}

在此我们用到若依框架封装的一个类SpringUtils,用来根据名称获取bean。

代码如下(直接复制粘贴即可):

@Component
public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware
{
    /** Spring应用上下文环境 */
    private static ConfigurableListableBeanFactory beanFactory;

    private static ApplicationContext applicationContext;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
    {
        SpringUtils.beanFactory = beanFactory;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
    {
        SpringUtils.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * 获取对象
     *
     * @param name
     * @return Object 一个以所给名字注册的bean的实例
     * @throws BeansException
     *
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) throws BeansException
    {
        return (T) beanFactory.getBean(name);
    }

    /**
     * 获取类型为requiredType的对象
     *
     * @param clz
     * @return
     * @throws BeansException
     *
     */
    public static <T> T getBean(Class<T> clz) throws BeansException
    {
        T result = (T) beanFactory.getBean(clz);
        return result;
    }

    /**
     * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
     *
     * @param name
     * @return boolean
     */
    public static boolean containsBean(String name)
    {
        return beanFactory.containsBean(name);
    }

    /**
     * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
     *
     * @param name
     * @return boolean
     * @throws NoSuchBeanDefinitionException
     *
     */
    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
    {
        return beanFactory.isSingleton(name);
    }

    /**
     * @param name
     * @return Class 注册对象的类型
     * @throws NoSuchBeanDefinitionException
     *
     */
    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException
    {
        return beanFactory.getType(name);
    }

    /**
     * 如果给定的bean名字在bean定义中有别名,则返回这些别名
     *
     * @param name
     * @return
     * @throws NoSuchBeanDefinitionException
     *
     */
    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
    {
        return beanFactory.getAliases(name);
    }

    /**
     * 获取aop代理对象
     *
     * @param invoker
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T getAopProxy(T invoker)
    {
        return (T) AopContext.currentProxy();
    }

    /**
     * 获取当前的环境配置,无配置返回null
     *
     * @return 当前的环境配置
     */
    public static String[] getActiveProfiles()
    {
        return applicationContext.getEnvironment().getActiveProfiles();
    }

    /**
     * 获取当前的环境配置,当有多个环境配置时,只获取第一个
     *
     * @return 当前的环境配置
     */
    public static String getActiveProfile()
    {
        final String[] activeProfiles = getActiveProfiles();
        return ObjectUtil.isNotNull(activeProfiles) ? activeProfiles[0] : null;
    }
}

3 最后我们创建一个入口,来进行测试

   @RequestMapping(value = "/test")
    public void test() throws InterruptedException {

        //  我们订三个业务线
        CountDownLatch latch = new CountDownLatch(3);

        //  创建三个工作对象
        Worker w1 = new Worker(latch,"小明");
        Worker w2 = new Worker(latch,"小红");
        Worker w3 = new Worker(latch,"小刚");

        //  执行线程
        ThreadUtil.execute(w1);
        ThreadUtil.execute(w2);
        ThreadUtil.execute(w3);

        //  等待所有的执行完毕
        latch.await();

        //  在此,所有线程执行完毕,可以做其他的啦!
        System.out.println("---所有人都干完了---");

    }

我们是使用hutool工具包ThreadUtil,直接创建的线程,当然,也可以用线程池等调用。

hutool工具包(没用过的同学,安利一下,很多封装好的工具类):

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.7.7</version>
</dependency>

最终输出结果:

Java之CountDownLatch的用法(多线程协同工作)_https://bianchenghao6.com/blog_Java_第1张

今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

发表回复