Java并发工具怎么用

发布时间:2021-10-11 11:01:11 作者:小新
来源:亿速云 阅读:101

这篇文章将为大家详细讲解有关Java并发工具怎么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

正文

1. 什么是并发工具

并发工具是一组工具类,主要是用来控制线程的执行流程,比如阻塞某个线程,以等待其他线程

2. 倒计数器 CountDownLatch

从字面意思来看,就是一个倒计数门闩(shuan,打了半天zha就是打不出来)

通俗一点来说,就是倒计数,时间一到,门闩就打开

注:一旦打开,就不能再合上,即这个 CountDownLatch 的状态改变是永久不可恢复的(记住这个点,后面会有对比)

比较官方的说法:倒计数器用来阻塞某个(某些)线程,以等待其他多个线程的任务执行完成(以这个说法为准,上面的可以用来对比参考)

下面列出 CountDownLatch 的几个方法:

模拟场景的话,这里先列举三个,肯定还有其他的

下面我们以第三个场景为例,写个例子:多人游戏加载画面

public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        // 1. 构造一个倒计数器,给定一个状态值10
        CountDownLatch latch = new CountDownLatch(10);
        System.out.println("准备加载");
      	// 这里我们创建10个线程,模拟 5V5 游戏的10个玩家
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                // 这里我们给点延时,模拟网络延时
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"加载100%");
                // 2. 这里的countDown就是用来改变倒计数器的内部状态,每次-1
                latch.countDown(); //这里不会阻塞当前线程,执行完后就立马返回了
            }).start();
        }
        // 3. 这里阻塞等待状态的完成,即10变为0;
        latch.await();
        System.out.println("所有人加载完成,开始游戏");
    }
}

输出如下:

准备加载
Thread-0加载100%
Thread-1加载100%
Thread-2加载100%
Thread-3加载100%
Thread-4加载100%
Thread-5加载100%
Thread-6加载100%
Thread-8加载100%
Thread-9加载100%
Thread-7加载100%
所有人加载完成,开始游戏

这里倒计数器的作用就是阻塞主线程,以等待其他10个子线程,等到都准备好,再恢复主线程

它的特点就是:一次性使用,达到终止状态后不能再改变

3. 倒计数器升级版 CyclicBarrier【循环栅栏】

循环栅栏,类似倒计数器,也是用来阻塞线程,不过它的重点在于循环使用

而倒计数器只能用一次(这属于他们之间最明显的一个区别)

PS:猜测之所以叫循环栅栏,而不是循环门闩,可能是因为栅栏的作用比门闩更强大,所以叫栅栏更适合吧

官方说法:循环栅栏一般用来表示多个线程之间的相互等待(阻塞)

比如有10个线程,都要await等待;那要等到最后一个线程await时,栅栏才会打开

如果有定义栅栏动作,那么当栅栏打开时,会执行栅栏动作

栅栏动作就是:栅栏打开后需执行的动作,通过构造函数的Runnable参数指定,可选参数,下面会介绍

这个属于循环栅栏和倒计数器的第二个区别

下面我们看几个循环栅栏 CyclicBarrier 内部的方法:

场景:

下面看下例子:多人游戏团战画面

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

        // 1. 创建一个循环栅栏,给定等待线程数10和栅栏动作
        CyclicBarrier barrier = new CyclicBarrier(10,()->{
            // 栅栏动作,等到所有线程都await,就会触发
            System.out.println("=== 人齐了,开始团吧");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        System.out.println("=== 准备第一波团战 ===");
        // 2. 创建10个线程,模拟10个玩家
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                try {
                    // 玩家到场
                    System.out.println(Thread.currentThread().getName()+"=>第一波团,我准备好了");
                    // 等待其他人,等人齐就可以团了(人齐了会执行栅栏动作,此时这边也会恢复执行)
                    barrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }).start();
        }
        // 3. 查询当前等待都线程数量,如果不为0,则主线程继续等待
        while (barrier.getNumberWaiting()!=0){
            Thread.sleep(1000);
        }
        System.out.println("=== 第一波团战结束 ===");
        
        // 4. 此时还可以进行第二波第三波团战。。。(循环栅栏可循环触发,倒计数器只能触发一次)
        
    }
}

输出如下:

=== 准备第一波团战 ===
Thread-0=>第一波团,我准备好了
Thread-1=>第一波团,我准备好了
Thread-2=>第一波团,我准备好了
Thread-3=>第一波团,我准备好了
Thread-4=>第一波团,我准备好了
Thread-5=>第一波团,我准备好了
Thread-6=>第一波团,我准备好了
Thread-7=>第一波团,我准备好了
Thread-8=>第一波团,我准备好了
Thread-9=>第一波团,我准备好了
=== 人齐了,开始团吧
=== 第一波团战结束 ===

4. 信号量 Semaphore

信号量主要是用来控制多个线程同时访问指定资源,比如数据库连接池,超过指定数量,就阻塞等待

下面我们介绍下信号量的几个关键方法:

场景:数据库连接池

信号量的特点就是可重复使用许可,所以像数据库连接池这种场景就很适合了

这里就不举例子了,就是多个线程acquire和release,获取许可时,如果没有就阻塞,如果有就立即返回

5 区别

用表格看比较方便点

区别CountDownLatchCyclicBarrierSemaphore
可使用次数单次多次(循环使用)多次(循环使用)
线程的阻塞阻塞单个(多个)线程,以等待其他线程的执行多个线程之间的相互阻塞超过许可数,会阻塞
场景1. 计数器<br />2. 统计任务执行时长<br />3. 多人对战游戏的开局等待1. 大事化小,再合并<br />2. 多人对战游戏的团战1. 数据库连接池

可以看到,倒计数器主要是用来表示单个线程等待多个线程,而循环栅栏主要是用来表示多个线程之间的相互等待

总结

  1. 什么是并发工具:并发工具是一组工具类,主要是用来控制线程的执行流程,比如阻塞某个线程,以等待其他线程

  2. 倒计数器 CountDownLatch:用来表示阻塞某个(某些)线程,以等待其他多个线程的任务执行完成

  3. 循环栅栏 CyclicBarrier:用来表示多个线程之间的相互等待协作(阻塞)

  4. 信号量 Semaphore:用来表示允许同时访问指定资源的许可数(线程数)

  5. 区别:

区别CountDownLatchCyclicBarrierSemaphore
可使用次数单次多次(循环使用)多次(循环使用)
线程的阻塞阻塞单个(多个)线程,以等待其他线程的执行多个线程之间的相互阻塞超过许可数,会阻塞
场景1. 计数器<br />2. 统计任务执行时长<br />3. 多人对战游戏的开局等待1. 大事化小,再合并<br />2. 多人对战游戏的团战1. 数据库连接池

关于“Java并发工具怎么用”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

推荐阅读:
  1. 如何浅析Java并发工具类在AQS实现
  2. Java并发工具辅助类的用法

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:Mac PHPStorm使用心得是什么

下一篇:如何实现微信图片加密解密

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》