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 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> JUC热榜前三的辅助类 -> 正文阅读

[游戏开发]JUC热榜前三的辅助类

JUC强大的辅助类

JUC 中提供了三种常用的辅助类,通过这些辅助类可以很好的解决线程数量过多时 Lock 锁的频繁操作。

这三种辅助类为:

? CountDownLatch: 减少计数

? CyclicBarrier: 循环栅栏

? Semaphore: 信号灯

① 减小计数 CountDownLatch (-1操作)

CountDownLatch 类可以设置一个计数器,然后通过 countDown 方法来进行减 1 的操作,使用 await 方法等待计数器不大于 0,然后继续执行 await 方法之后的语句。

? CountDownLatch 主要有两个方法,当一个或多个线程调用 await 方法时,这些线程会阻塞

? 其它线程调用 countDown 方法会将计数器减 1(调用 countDown 方法的线程不会阻塞)

? 当计数器的值变为 0 时,因 await 方法阻塞的线程会被唤醒,继续执行

允许一个或多个线程等待直到在其他线程中执行的一组操作完成的同步辅助。
A CountDownLatch用给定的计数初始化。 await方法阻塞,直到由于countDown()方法的调用而导致当前计数达到零,之后所有等待线程被释放,并且任何后续的await 调用立即返回。 这是一个一次性的现象 - 计数无法重置。

场景: 6 名同学陆续离开教室后值班同学才可以关门。

不使用CountDownLatch的方法

public class CountDownLatchDemo {
    //不加CountDownLatchDemo,6 个同学陆续离开教室后值班同学才可以关门。
    public static void main(String[] args) {
        for (int i = 1; i <= 6; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+" 号同学离开教室");
            },String.valueOf(i)).start();
        }
        System.out.println("班长锁门走人");
    }
}

结果出现异常,班长锁门,其余同学依然可以出教室。

1 号同学离开教室
2 号同学离开教室
班长锁门走人
4 号同学离开教室
6 号同学离开教室
3 号同学离开教室
5 号同学离开教室

使用CountDownLatch

public class CountDownLatchDemo {
    //加CountDownLatchDemo,6 个同学陆续离开教室后值班同学才可以关门。
    public static void main(String[] args) {
        //CountDownLatchDemo创建CountDownLatchDemo对象,设置初始值
        CountDownLatch countDownLatch = new CountDownLatch(6);

        for (int i = 1; i <= 6; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+" 号同学离开教室");
                //计数减一
                countDownLatch.countDown();
            },String.valueOf(i)).start();
        }
        //等待计数器为0后,执行await之后的语句
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("班长锁门走人");
    }
}

结果正常:

1 号同学离开教室
5 号同学离开教室
6 号同学离开教室
4 号同学离开教室
3 号同学离开教室
2 号同学离开教室
班长锁门走人

进程已结束,退出代码为 0

② 循环栅栏 CyclicBarrier (+1操作)

在这里插入图片描述

允许一组线程全部等待彼此达到共同屏障点的同步辅助。 循环阻塞在涉及固定大小的线程方的程序中很有用,这些线程必须偶尔等待彼此。 屏障被称为循环 ,因为它可以在等待的线程被释放之后重新使用。
CyclicBarrier支持一个可选的Runnable命令,每个屏障点运行一次,在派对中的最后一个线程到达之后,但在任何线程释放之前。 在任何一方继续进行之前,此屏障操作对更新共享状态很有用。

CyclicBarrier 看英文单词可以看出大概就是循环阻塞的意思,在使用中CyclicBarrier 的构造方法第一个参数是目标障碍数,每次执行 CyclicBarrier 一 次障碍数会加一,如果达到了目标障碍数,才会执行 cyclicBarrier.await()之后的语句。可以将 CyclicBarrier 理解为加 1 操作

CyclicBarrier(int parties, Runnable barrierAction)
创建一个新的 CyclicBarrier ,当给定数量的线程(线程)等待时,它将跳闸,当屏障跳闸时执行给定的屏障动作,由最后一个进入屏障的线程执行。

场景: 集齐 7 颗龙珠就可以召唤神龙

package com.juc;

import java.util.concurrent.CyclicBarrier;

//集齐7颗龙珠就可以召唤神龙
public class CyclicBarrierDemo {

    //创建固定值
    private static final int NUMBER = 7;

    public static void main(String[] args) {
        //创建CyclicBarrier
        CyclicBarrier cyclicBarrier =
                new CyclicBarrier(NUMBER, () -> {
                    System.out.println("*****集齐7颗龙珠就可以召唤神龙");
                });

        //集齐七颗龙珠过程
        for (int i = 1; i <= 7; i++) {
            new Thread(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + " 星龙被收集到了");
                    //等待计数器为7,执行await后面的方法
                    cyclicBarrier.await();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }, String.valueOf(i)).start();
        }
    }
}

结果:

1 星龙被收集到了
6 星龙被收集到了
3 星龙被收集到了
5 星龙被收集到了
2 星龙被收集到了
7 星龙被收集到了
4 星龙被收集到了
*****集齐7颗龙珠就可以召唤神龙

③ 信号灯 Semaphore

Semaphore 的构造方法中传入的第一个参数是最大信号量(可以看成最大线程池),每个信号量初始化为一个最多只能分发一个许可证。使用 acquire 方法获得许可证,release 方法释放许可

acquire()
从该信号量获取许可证,阻止直到可用,或线程为 interrupted 。

release()
释放许可证,将其返回到信号量。

场景: 抢车位, 6 部汽车 3 个停车

public class SemaphoreDemo {

    public static void main(String[] args) {
        //创建Semaphore对象
        Semaphore semaphore = new Semaphore(3);
        //模拟6辆汽车
        for(int i=1;i<=6;i++){
            new Thread(()->{
                //抢占车位
                try {
             	   //获取许可证
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName()+"辆车抢到了车位");
                    //设置随即停车时间
                    TimeUnit.SECONDS.sleep(new Random().nextInt(5));
                    System.out.println(Thread.currentThread().getName()+"辆车离开了车位");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                	//释放许可证
                    semaphore.release();
                }

                //释放车位
                System.out.println();
            },String.valueOf(i)).start();
        }


    }
}

结果:

1辆车抢到了车位
2辆车抢到了车位
3辆车抢到了车位
1辆车离开了车位
3辆车离开了车位

4辆车抢到了车位

5辆车抢到了车位
4辆车离开了车位
2辆车离开了车位

6辆车抢到了车位
6辆车离开了车位

5辆车离开了车位

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-04-29 12:26:54  更:2022-04-29 12:27:55 
 
开发: 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 14:58:00-

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