Java系列:Java 多线程条件通行工具——CountDownLatch

CountDownLatch


前言

今天博主将为大家分享一下使用Java 多线程条件通行工具——CountDownLatch,不喜勿喷,如有异议欢迎讨论!

  • CountDownLatch和CyclicBarrier的区别,其实比较简单,CountDownLatch对执行任务的线程。比如有A,B,C三个线程,那么如果A是设置了countDown.await()这个方法,那么B和C就只能等到A了,什么时候A准备好了,那么B和C才可以执行.

  • 典型的场景就是,比如A需要从远程服务器拿到某个资源,然后B和C的执行,需要依赖A这个资源,但是又可能,A执行的时候,拿到的资源还是空的或者没有就绪,那么只有通过在主线程里,另外起一个线程,比如叫D吧,他循环判断A请求的资源是否就绪,而在主线程里在B和C执行以前,统一设置一个 countDown.await()方法。只有当D确认资源状态以后,并且调用了 countDown.countDown(2) 这里是2是假设的,到0,就表示OK了,那么被等待的方法才能继续执行下去

  • 而 CyclicBarrier呢,A B C三个都要准备好了,不然没有办法继续下去.


以下所写内容均与以前的文章有联系可以前往博文查看,陈永佳的博客


CountDownLatch的作用

线程进入等待后,需要计数器达到0才能通行。

  • CountDownLatch(int)
    构造方法,指定初始计数。
  • await()
    等待计数减至0。
  • await(long, TimeUnit)
    在指定时间内,等待计数减至0。
  • countDown()
    计数减1。
  • getCount()
    获取剩余计数。

例子1:主线程创建了若干子线程,主线程需要等待这若干子线程结束后才结束。

例子2:线程有若干任务,分多个线程来完成,需要等待这若干任务被完成后,才继续运行处理。

源码如下:

/**
 * @since 1.5
 * @author Doug Lea
 */
public class CountDownLatch {

    private final Sync sync;

    public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }
    
    private static final class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 4982264981922014374L;

        Sync(int count) {
            setState(count);
        }

        int getCount() {
            return getState();
        }

        protected int tryAcquireShared(int acquires) {
            // 当数量达到0时,才能通行,否则阻塞
            return (getState() == 0) ? 1 : -1;
        }

        protected boolean tryReleaseShared(int releases) {
            for (;;) {
                int c = getState();
                // 如果数量达到0,则释放失败
                if (c == 0)
                    return false;
                int nextc = c-1;
                // 尝试把数量递减
                if (compareAndSetState(c, nextc))
                    return nextc == 0;
            }
        }
    }

    public void await() throws InterruptedException {
        // 获取共享锁
        sync.acquireSharedInterruptibly(1);
    }

    public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
        // 尝试获取共享锁
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }

    public void countDown() {
        // 释放共享锁
        sync.releaseShared(1);
    }

    public long getCount() {
        return sync.getCount();
    }

    public String toString() {
        return super.toString() + "[Count = " + sync.getCount() + "]";
    }
}

给个栗子,代码如下:

package com.test;

import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.CountDownLatch;

/**
 * 
 * @Description: Java 多线程条件通行工具——CountDownLatch
 * @ClassName: CountDownLatch.java
 * @author ChenYongJia
 * @Date 2019年4月17日 晚上22:54
 * @Email chen87647213@163.com
 */
public class CountDownLatchTest {

	public static void main(String[] args) throws InterruptedException {

		CountDownLatchTest test = new CountDownLatchTest();

		CountDownLatch latch = new CountDownLatch(1);

		Thread t1 = new Thread(test.new MapOper(latch));
		Thread t2 = new Thread(test.new MapOper(latch));
		Thread t3 = new Thread(test.new MapOper(latch));
		Thread t4 = new Thread(test.new MapOper(latch));

		t1.setName("Thread1");
		t2.setName("Thread2");
		t3.setName("Thread3");
		t4.setName("Thread4");
		t1.start();
		t2.start();
		t3.start();
		t4.start();

		System.out.println("线程已经启动,休眠一会儿...");

		Thread.sleep(1000);
		latch.countDown();

	}

	public class MapOper implements Runnable {

		CountDownLatch latch;

		public MapOper(CountDownLatch latch) {
			this.latch = latch;
		}

		public void run() {
			try {
				latch.await();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + " 同步开始!");
		}
	}

}

控制台输出:

线程已经启动,休眠一会儿...
Thread2 同步开始!
Thread3 同步开始!
Thread1 同步开始!
Thread4 同步开始!

到这里使用Java 多线程条件通行工具——CountDownLatch讲解完毕了,下一篇将为大家讲解Java 多线程条件通行工具——CyclicBarrier!


最后

  • 更多参考精彩博文请看这里:《陈永佳的博客》

  • 喜欢博主的小伙伴可以加个关注、点个赞哦,持续更新嘿嘿!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈永佳

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值