IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> [多线程] 多线程工具之CountDownLatch -> 正文阅读

[Java知识库][多线程] 多线程工具之CountDownLatch

前言

在Java中, 如何启动多个线程. 随后使某项任务分步执行.

(TODO 此处可以来2个说明图和小故事.)


使用Join方法

public static Main(String []args){
	// 声明线程
	Thread threadA1 = new Thread();
	Thread threadA2 = new Thread();
	Thread threadA3 = new Thread();
	// 启动线程
    threadA1.start();
    threadA2.start();
    threadA3.start();
	// 卡死线程 等到A1 A2 A3都执行完毕后 再执行下方代码
    threadA1.join();
    threadA2.join();
    threadA3.join();
	
	// 声明B组线程 
	Thread threadB1 = new Thread();
	Thread threadB2 = new Thread();
	// 启动B组线程
	threadB1.start();
	threadB2.start();
}

使用CountDownLatch

CountDownLatch 内核心方法:

  • await(): 等待. 当count值为0时, 才能继续执行.
  • countDown(): 和方法名一样. 具体作用时将方法名称-1.
  • getCount(): 获取当前count值.

简单都小测试

import java.util.concurrent.CountDownLatch;

public class TestJava {

    public static final CountDownLatch countDownLatch = new CountDownLatch(3);

    public static void main(String[] args) throws InterruptedException {
        Thread threadA1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("AThreadName: "+Thread.currentThread().getName()+" - "+ "count:"+ countDownLatch.getCount());
                countDownLatch.countDown();
            }
        });
        Thread threadA2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("AThreadName: "+Thread.currentThread().getName()+" - "+ "count:"+ countDownLatch.getCount());
                countDownLatch.countDown();
            }
        });
        Thread threadA3 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("AThreadName: "+Thread.currentThread().getName()+" - "+ "count:"+ countDownLatch.getCount());
                countDownLatch.countDown();
            }
        });
        threadA1.start();
        threadA2.start();
        threadA3.start();
        // 等待3个线程都执行完成
        countDownLatch.await();
        Thread threadB1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("BThreadName: "+Thread.currentThread().getName()+" - "+ "count:"+ countDownLatch.getCount());
            }
        });
        Thread threadB2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("BThreadName: "+Thread.currentThread().getName()+" - "+ "count:"+ countDownLatch.getCount());
            }
        });
        threadB1.start();
        threadB2.start();
    }


}
  • 测试结果
    感兴趣的小伙伴可以本地运行下这段程序. 笔者运行这段程序结果如下所示:
AThreadName: Thread-0 - count:3
AThreadName: Thread-1 - count:2
AThreadName: Thread-2 - count:1
BThreadName: Thread-3 - count:0
BThreadName: Thread-4 - count:0

可以看到. A线程解锁的程序先执行. B线程解锁的程序后执行. 这样就能控制A任务组执行完成后, 才执行B任务组. 这在开发过程中也经常用到.

比如你的产品有2个步骤: 1. 验证数据 2. 插入数据. 当数据时成批处理的时候, 我们一般会希望任务1执行完成后, 再进行任务2的处理. 此时使用CountDownLatch准没错. 当然, 此工具类也有一定的局限性. 就是Count只能删除, 并不能重置. 这点, 我么在下一章CycleBarrier中再提及这点.


实现细节

CountDownLatch其实也是使用AQS对Java中锁的一种实现方式. 有空的话可以详细解读下具体实现.

package java.util.concurrent;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;

从包名可以看出. 其时属于java.util.concurrent包下的. 属于官方的提供的一个工具包.

在这里插入图片描述
我们再来看下类图. 这个类非常简单, 无继承类. 基础的时默认基类Object. 其中的核心方法主要就是3个. await()/await(long, TimeUnit)后面这个应该是设置了超时时间, 为了防止死锁. countDown()减少count的值.

随后. 我们可以看下具体实现.

  • 局部类Sync. 其主要实现了AQS.
    /**
     * Synchronization control For CountDownLatch.
     * Uses AQS state to represent count.
     */
    private static final class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 4982264981922014374L;
		
		// 通过count记录状态值 主要分为0和非0 这2种情况
        Sync(int count) {
            setState(count);
        }

        int getCount() {
            return getState();
        }
		
		// 主要重写方法1 当state 也就是count为0时才能获取Shared锁
        protected int tryAcquireShared(int acquires) {
            return (getState() == 0) ? 1 : -1;
        }
		
		// 主要重写方法2 
        protected boolean tryReleaseShared(int releases) {
            // Decrement count; signal when transition to zero
            for (;;) {
                int c = getState();
                if (c == 0)
                    return false;
                int nextc = c-1;
                // 使用cas 让c=c-1 .
                if (compareAndSetState(c, nextc))
                	// 成功-1. 但是返回前再判断下当前锁是否已经停止了
                    return nextc == 0;
            }
        }
    }
  • 其余方法
    private final Sync sync;
    // 构造方法
    public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }
    // 等待
        public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }
    // 等待 并设置超时时间
        public boolean await(long timeout, TimeUnit unit)
        throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }
    // 让count值-1
        public void countDown() {
        sync.releaseShared(1);
    }
    // 获取当前count值. 在上方可以看到是通过getState()方法进行实现的.
        public long getCount() {
        return sync.getCount();
    }
    // 重写父类 toString方法 没啥意思
        public String toString() {
        return super.toString() + "[Count = " + sync.getCount() + "]";
    }


后记在这里插入图片描述

在这里插入图片描述
顺便随便看了一眼Java的这些工具包. 好家伙,还真不少. 有机会都撸一遍吧.


Reference

[1] JDK核心源码: java.util.concurrent.CountDownLatch

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-10-11 17:22:52  更:2021-10-11 17:25:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 22:36:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码