CountDownLatch的简单使用——Java并发编程

本文详细介绍了Java CountDownLatch同步工具的原理、API使用方法,并通过示例展示了如何在多线程环境中作为信号量控制线程执行。理解CountDownLatch如何作为开/关锁和任务完成计数器,有助于提升并发编程效率。
摘要由CSDN通过智能技术生成

Java并发编程

CountDownLatch的使用

允许一个或多个线程等待直到在其他线程中执行的一组操作完成的同步辅助。

简述

CountDownLatch用给定的计数初始化。 await方法阻塞,直到由于countDown()方法的调用而导致当前计数达到零,之后所有等待线程被释放,并且任何后续的await 调用立即返回。 这是一个一次性的现象 - 计数无法重置。 如果需要重置计数的版本,请考虑使用CyclicBarrier

CountDownLatch是一种通用的同步工具,可用于多种用途。 一个CountDownLatch为一个计数的CountDownLatch用作一个简单的开/关锁存器,或者门:所有线程调用await在门口等待,直到被调用countDown()的线程打开。 一个CountDownLatch初始化N可以用来做一个线程等待,直到N个线程完成某项操作,或某些动作已经完成N次。

CountDownLatch一个有用的属性是,它不要求调用countDown线程等待计数到达零之前继续,它只是阻止任何线程通过await ,直到所有线程可以通过。

也就是相当于一个高铁检票口,需要在时间倒数到检票时间的时候,才会放行,不然,都得在候车厅等待。此时高铁就如同需要执行的下一个任务,乘客就相当于阻塞的线程。

API

其实对于这个类而言,涉及到的方法不多,只有下面的几个,所以运用也不是很难。

Modifier and TypeMethod and Description
voidawait() 导致当前线程等到锁存器计数到零,除非线程是 interrupted
booleanawait(long timeout, TimeUnit unit) 使当前线程等待直到锁存器计数到零为止,除非线程为 interrupted或指定的等待时间过去。
voidcountDown() 减少锁存器的计数,如果计数达到零,释放所有等待的线程。
longgetCount() 返回当前计数。
StringtoString() 返回一个标识此锁存器的字符串及其状态。

示例程序

package CountDownLatchLearn;

import java.util.concurrent.CountDownLatch;

public class Latch {

    static class MyService {
        private CountDownLatch latch = new CountDownLatch(3);

        public void testMethod() {
            try {
                if (Thread.currentThread().getName().equals("线程4")) {
                    Thread.sleep(3000);
                }
                System.out.println(Thread.currentThread().getName() + "准备");
                latch.await();
                System.out.println(Thread.currentThread().getName() + "结束");
            } catch (InterruptedException e) {
                System.out.println("Exception:" + e);
                e.printStackTrace();
            }
        }

        public void downMethod() {
            latch.countDown();
        }
    }

    static class MyThread extends Thread {
        private MyService myService;

        public MyThread(MyService myService) {
            super();
            this.myService = myService;
        }

        @Override
        public void run() {
            myService.testMethod();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MyService service = new MyService();
        MyThread[] threads = new MyThread[10];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new MyThread(service);
            threads[i].setName("线程" + (i + 1));
            threads[i].start();
        }
        System.out.println("预备");
        for (int i = 3; i >= 1; i--) {
            System.out.println(i);
            Thread.sleep(1000);
            service.downMethod();
        }
        System.out.println("====START====");
    }

}

在这个简单的程序中,设计的是一个起跑发令,主线程main用于放行所有准备好的线程,其中我专门设计一个线程的准备时间超过了main的最长等待时间,我们可以通过运行结果看出一点问题:

预备
3
线程3准备
线程10准备
线程1准备
线程9准备
线程2准备
线程6准备
线程7准备
线程8准备
线程5准备
2
1
====START====
线程10结束
线程6结束
线程1结束
线程9结束
线程3结束
线程7结束
线程4准备 =====> 别人都起跑了,才准备好
线程2结束
线程5结束
线程8结束
线程4结束

Process finished with exit code 0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值