【JAVAEE】JUC(java.util.concurrent)的常见类

news2024/11/27 4:38:35

目录

1.Callable接口

1.1简介

1.2代码演示

 1.3Runnable与Callable的区别

2.ReentrantLock

2.1ReentrantLock的常用方法

2.2ReentrantLock的代码演示

2.3ReentrantLock和synchronized的区别

3.Semaphore信号量

3.1概念

3.2代码演示

4.CountDownLatch

4.1概念

4.2代码演示


JUC是java.util.concurrent包的简称,JDK1.5之后对多线程的一种实现,这个包下放的类都和多线程有关,提供了很多工具类。

1.Callable接口

1.1简介

Callable是一个interface。相当于把线程封装了一个“返回值”,方便程序员借助多线程的方式计算得出结果。

Callable是创建线程的一种的方式,与Runnable类似。

当你的任务需要返回值时,用Callable比较好。

1.2代码演示

先定义一个线程的任务(从1加到10的结果)

    public static void main(String[] args) {
        //先定义一个线程的任务
        Callable<Integer>callable=new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                int sum=0;
                for (int i = 0; i < 10; i++) {
                    sum+=i;
                }
                return sum;
            }
        };
    }

使用FutureTask类来创建一个对象,这个对象持有callable。执行任务并获取结果。

(FutureTask是Runnable的一个实现类,所以可以传入Thread的构造方法中)

        //通过FutureTask类来创建一个对象,这个对象持有callable
        FutureTask<Integer>futureTask=new FutureTask<>(callable);
        //创建线程并指定任务
        Thread thread=new Thread(futureTask);
        //让线程执行定义好的任务
        thread.start();
        //获取线程执行的结果
        Integer result=futureTask.get();
        //打印结果
        System.out.println(result);

实现结果:

 1.3Runnable与Callable的区别

如上图所示:

 ①Callable实现的是Call方法,Runnable实现的是Run方法

②Callable可以返回一个结果,Runnable不能返回结果

③Callable要配合FutureTask一起使用

④Callable可以抛出异常,Runnable不可以

2.ReentrantLock

可重入互斥锁,和synchronized定位类似,都是用来实现互斥效果,保证线程安全。是基于CAS实现的一个纯用户态的锁。

2.1ReentrantLock的常用方法

常用方法:

lock():加锁,如果获取不到锁就死等

trylock():尝试加锁

unlock():解锁

常用方法的使用代码演示:

    public static void main(String[] args) throws InterruptedException {
        //创建一个ReentrantLock锁对象
        ReentrantLock reentrantLock=new ReentrantLock();
        //加锁
        reentrantLock.lock();
        //尝试加锁,死等
        reentrantLock.tryLock();
        //尝试加锁,有超时时间
        reentrantLock.tryLock(1, TimeUnit.SECONDS);
        //释放锁
        reentrantLock.unlock();
    }

2.2ReentrantLock的代码演示

模拟业务中出现异常情况时,如何释放锁:

    //模拟业务中如果出现异常情况,如何释放锁
    public static void Demo02() throws Exception {
        //创建一个ReentrantLock锁对象
        ReentrantLock reentrantLock=new ReentrantLock();
        try {
            //加锁
            reentrantLock.lock();
            //TODO:业务逻辑
            throw new Exception("业务出现异常");
        }finally {
            //保证出现异常的时候也可以释放锁
            reentrantLock.unlock();
        }

    }

演示创建一个公平锁(默认为false):

    //演示创建一个公平锁
    public static void demo03(){
        //创建一个ReentrantLock锁对象,通过构造方法,传入true时为公平锁,默认为false
        ReentrantLock reentrantLock=new ReentrantLock(true);
    }

演示创建一个读写锁:

    //演示创建一个读写锁
    public static void demo04(){
        //创建
        ReentrantReadWriteLock readWriteLock=new ReentrantReadWriteLock();
        //获取读锁,共享锁,读与读可以同时进行
        readWriteLock.readLock();
        //获取写锁,排他锁(互斥锁),读写,写读,写写都不能共存
        readWriteLock.writeLock();
    }

ReentrantLock可以根据不同的Condition去休眠或唤醒线程。

演示:

两个条件:1.只处理男生任务

                  2.只处理女生任务

    private static ReentrantLock reentrantLock=new ReentrantLock();
    //定义不同的条件
    private static Condition boyCondition = reentrantLock.newCondition();
    private static Condition girlCondition = reentrantLock.newCondition();

    public static void demo05() throws InterruptedException {
        Thread threadBoy = new Thread(() -> {
            // 让处理男生任务的线程去休眠
            try {
                boyCondition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 唤醒处理女生任务的线程
            girlCondition.signalAll();
        });

        Thread threadGirl = new Thread(() -> {
            // 让处理女生任务的线程去休眠
            try {
                girlCondition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 唤醒处理男生任务的线程
            boyCondition.signalAll();
        });
    }

2.3ReentrantLock和synchronized的区别

区别:

①synchronized使用时不需要手动释放锁,ReentrantLock使用时需要手动释放,使用起来更灵活,但是也容易遗漏unlock

②sychronized在申请锁失败时,会一直等待锁资源,ReentrantLock可以通过trylock的方式等待一段时间就放弃

③synchronized是非公平锁,ReentrantLock默认是非公平锁。可以通过构造方法传入一个true开启公平锁模式

④synchronized是一个关键字,是JVM内部实现的,ReentrantLock是标准库的一个类,基于Java JUC实现

3.Semaphore信号量

3.1概念

信号量,用来表示“可用资源的个数”。本质上就是一个计数器。

理解信号量:

停车场外的显示屏上通常会显示当前停车场李可用的车位个数,车位个数相当于是可用资源。

1.当一辆车入场后,相当于申请一个资源,车位的个数就减一(这个称为信号量的 P 操作)

2.当一辆车离开时,相当于释放一个资源,车位的个数就加一(这个称为信号量的 V 操作)

3.停车场所有的车位就是可以显示的最大有效值

申请资源的时候,当资源已经被用完,那么线程申请的时候就会阻塞等待。

补充:当代码需要指定有限的资源个数时,可以考虑使用Semaphore来处理。

3.2代码演示

定义一个信号量,指定可用资源个数为3

    //定义一个信号量,指定可用资源个数
    private static Semaphore semaphore=new Semaphore(3);

模拟业务处理

    public static void main(String[] args) {
        //定义一个任务
        Runnable runnable=new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println(Thread.currentThread().getName()+"[+]申请资源");
                    //调用此方法,可用资源数减一
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName()+"[!]申请到资源");
                    //模拟业务处理
                    TimeUnit.SECONDS.sleep(1);
                    //释放资源
                    semaphore.release();
                    System.out.println(Thread.currentThread().getName()+"[-]释放了资源");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        };

        //创建多个线程
        for (int i = 0; i < 20; i++) {
            Thread thread=new Thread(runnable);
            thread.start();
        }
    }

当申请资源满了时,就会阻塞等待。

4.CountDownLatch

4.1概念

同时等待N个任务执行结束。

理解CountDownLatch:

好像跑步比赛,10个选手依次就位,哨声响起才同时出发,所有选手都通过终点,才能结束比赛。

作用:可以设置所有的线程必须都到达某一个关键点然后再执行后续的操作。

4.2代码演示

演示跑步比赛:

定义一个CountDownLatch,参数为10代表10个选手

    //定义一个CountDownLatch
    private static CountDownLatch countDownLatch=new CountDownLatch(10);

创建线程,模拟10个选手比赛,直到10个选手都到达终点才会颁奖

    public static void main(String[] args) throws InterruptedException {
        System.out.println("所有选手各就各位");
        //创建线程,模拟跑步比赛
        for (int i = 0; i < 10; i++) {
            Thread thread=new Thread(()->{
                System.out.println(Thread.currentThread().getName()+"出发");
                //模拟比赛过程
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //到达终点,计数减一
                countDownLatch.countDown();
                System.out.println(Thread.currentThread().getName()+"到达终点");
            },"player"+(i+1));
            thread.start();
        }
        //等待所有线程执行完成
        //一直等到countDownLatch为0时才会执行之后的代码
        countDownLatch.await();
        //颁奖
        System.out.println("开始颁奖");
    }

运行结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/533637.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【SpringBoot整合RabbitMQ(下)】

八、死信队列 先从概念解释上搞清楚这个定义&#xff0c;死信&#xff0c;顾名思义就是无法被消费的消息&#xff0c;字面意思可以这样理解&#xff0c;一般来说&#xff0c;producer 将消息投递到 broker 或者直接到 queue 里了&#xff0c; consumer 从 queue 取出消…

用Pin自动对二进制文件脱壳

Intel Pin Intel Pin在可执行二进制代码中插入一些探测函数,用于观察、记录、分析宿主代码执行过程中的一些与计算机体系结构相关的特性,如访存指令,寄存器内容,寄存器地址等,通过Pin提供的API可以编写各种分析函数,这样程序运行完以后,统计和分析结果也同时产生,分析…

I3D--视频理解必读论文总结

论文标题&#xff1a;Quo Vadis, Action Recognition? A New Model and the Kinetics会议期刊&#xff1a; CVPR 2017Dataset 论文地址&#xff1a;https://arxiv.org/pdf/1705.07750.pdf 文章目录 前言文章核心摘要引入方法a. 2DConvLSTMb. 3DConvc d. Two-StrwamTwo-Stream …

C语言学习分享(第七次)------操作符

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:C语言学习分享⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多C语言知识   &#x1f51d;&#x1f51d; 操作符详解 1. 前言&#x1f6a9;2…

Ajax,前后端分离开发,前端工程化,Element,Vue路由,打包部署

Ajax介绍 Axios <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-wid…

为什么我掌握了大量软测知识,却还是找不到工作?

很多朋友都在疑惑&#xff0c;为什么随着对于软件测试了解的加深&#xff0c;不断掌握更多测试知识与技巧&#xff0c;找工作貌似越来越难了&#xff1f; 不免让人联想到最近偶然间看到一句话&#xff1a;“软件测试是整个 IT 行业中最差的岗位”。 打工人的问题出在哪&#xf…

使用Jmeter应该如何进行http接口性能测试?

在进行网页或应用程序后台接口开发时&#xff0c;一般要及时测试开发的接口能否正确接收和返回数据&#xff0c;对于单次测试&#xff0c;Postman插件是个不错的Http请求模拟工具。 但是Postman只能模拟单客户端的单次请求&#xff0c;而对于模拟多用户并发等性能测试&#xff…

11.1网络编程——

多线程 一、基础知识概念相关API二、任务创建一个简单的本地客户端创建一个简单的本地服务器三、总结四、问题一、基础知识 概念 网络编程中客户端和服务器指的是进程,而不是常提到的机器或者主机。注意三个概念:请求、响应、事务。 网络编程中客户端-服务器事务是指客户端和…

刷题day65:分割等和子集

题意描述&#xff1a; 给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集&#xff0c;使得两个子集的元素和相等。 思路&#xff1a; 使用01背包&#xff0c; 背包的体积为sum / 2背包要放入的商品&#xff08;集合里的元素&#xff09;…

linux数据校验

文件 一般对于文件的校验使用md5&#xff0c;centos7系统有自带的md5校验工具md5sum&#xff0c;可以用来校验两个文件是否一致 可以对比一下md5值是否一致来校验文件是否一致 目录 1 若是在主机上使用网络磁盘挂载备份的可以使用diff工具对比两个目录是否一致 diff -r /op…

Nginx使用教程

目录 一、Nginx介绍二、下载和安装三、Nginx命令1.查看版本2.检查配置文件正确性3.启动和停止4.重新加载配置文件 四、配置文件结构五、Nginx具体应用1.部署静态资源2.反向代理3.负载均衡 一、Nginx介绍 Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件( IMAP/POP3)代…

少儿编程 中国电子学会图形化编程等级考试Scratch编程二级真题解析(选择题)2023年3月

2023年3月scratch编程等级考试二级真题 选择题(共25题,每题2分,共50分) 1、小猫的程序如图所示,积木块的颜色与球的颜色一致。点击绿旗执行程序后,下列说法正确的是 A、小猫一直在左右移动,嘴里一直说着“抓到了”。 B、小猫会碰到球,然后停止。 C、小猫一直在左右…

《LKD3粗读笔记》(13)虚拟文件系统

《LKD3粗读笔记》(13)虚拟文件系统 虚拟文件系统&#xff0c;简称VFS&#xff0c;是内核的子系统&#xff0c;为用户空间程序提供了文件系统相关的接口。系统中所有文件系统不但依赖VFS共存&#xff0c;而且也依靠VFS系统协同工作。通过虚拟文件系统&#xff0c;程序可以利用标…

文本三剑客正则表达式2

文章目录 文本三剑客&正则表达式21 sed2 sed命令的常用选项3 sed命令的操作符4 打印4.1 按照行号寻址打印4.1.1 只打印第二行4.1.2 只显示行号4.1.3 显示行号及内容4.1.4 只打印最后一行 4.2 进行行号范围区间的打印4.2.1 打印1-3行4.2.2 打印第二行到最后一行4.2.3 打印2-…

操作符续(整型提升与算术转换)

&#x1f929;本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 &#x1f970;内容专栏&#xff1a;这里是《C知识系统分享》专栏&#xff0c;笔者用重金(时间和精力)打造&#xff0c;基础知识一网打尽&#xff0c…

MySQL深入浅出: order by if()与order by in()之条件排序

目录 1&#xff1a;原表数据 2&#xff1a;order by if&#xff08;&#xff09; 3&#xff1a;order by in&#xff08;&#xff09; 4&#xff1a;社区地址 1&#xff1a;原表数据 2&#xff1a;order by if&#xff08;&#xff09; SELECT * FROM people ORDER BY IF(…

mysql数据库的表的增删查改

目录 表的增删查改 6.1&#xff1a;增加 6.2&#xff1a;查找 6.3&#xff1a;更新 6.4&#xff1a;删除 6.5&#xff1a; 插入查询结果 6.6&#xff1a;聚合函数 6.7&#xff1a;group by分组 关键字的先后顺序&#xff1a;from > on> join > where > gro…

C语言实现三子棋小游戏

目录 游戏介绍 游戏菜单的创建&#xff08;menu&#xff09; 游戏核心功能实现 棋盘的初始化&#xff08;InitBoard&#xff09; 棋盘的展现&#xff08;printfboard&#xff09; 玩家下棋&#xff08;playerBoard&#xff09; 电脑下棋&#xff08;computerBoard&#…

探究C++构造函数及其优化

目录 一、 类的六个默认成员函数1.1 框架图1.2 具体介绍&#xff08;1&#xff09;构造函数&#xff08;2&#xff09;析构函数&#xff08;3&#xff09;拷贝构造函数&#xff08;4&#xff09;赋值运算符重载函数 归纳我们不写&#xff0c;编译器默认生成了什么&#xff1a; …

2023宁波市赛 天一永安杯赛前模拟题部分wp

Web pop 进hint.php 伪协议读index.php <?php class Tiger{public $string;protected $var;// 恶意参数public function __construct($var){$this->var $var;}public function __toString(){return $this->string;}public function boss($value){// 0eval($valu…