【Java多线程】面试常考 —— JUC(java.util.concurrent) 的常见类

目录

1、JUC(java.util.concurrent)

1.1、Callable 接口

1.2、ReentrantLock 可重入锁

1.3、Semaphore 信号量

1.4、CountDownLatch



1、JUC(java.util.concurrent)

这是java中的一个包,存放着多线程编程中常见的一些类。

1.1、Callable 接口

【Java多线程】Thread类的基本用法-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/zzzzzhxxx/article/details/136121421?spm=1001.2014.3001.5501

往期的博客中对创建线程的几种方式进行过说明,有如下几种:

1、继承 Thread(包含了匿名内部类的方式)

2、实现 Runnable(包含了匿名内部类的方式)

3、基于 lambda 表达式

其实除了以上方式,还有一个方式可以创建线程,即基于 Callable 的创建方法

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Callable<Integer> callable = new Callable<>() {
            @Override
            public Integer call() throws Exception {
                int ret = 0;
                for (int i = 1; i <= 1000; i++) {
                    ret += i;
                }
                return ret;
            }
        };

        //引入 FutureTask 类,作为 Thread 和 callable 的 “粘合剂”
        FutureTask<Integer> futureTask = new FutureTask<>(callable);
        Thread t = new Thread(futureTask);
        t.start();

        //取餐号,使用 futureTask 获取到结果,具有阻塞功能
        System.out.println(futureTask.get());
    }

基于 Callable 同样可以创建线程,那么它与 Runnable 有什么区别呢?

  • Runnable 关注的是整个过程,不关注执行结果,Runnable 提供的是 run 方法,返回值类型是 void。
  • Callable 关注的是执行结果,Callable 提供的是 call 方法,返回值就是线程执行任务得到的结果。

因此,如果编写多线程代码时,希望关注线程中代码的返回值时,此时使用基于 Callable 实现的线程更为方便。

1.2、ReentrantLock 可重入锁

与 synchronized 有区别,上古时期的 Java,synchronized 还不够强壮,功能也不够强大,也没有各种优化,当时 ReenactmentLock 就是实现可重入锁的选择。

ReenactmentLock 的用法具有传统锁的风格,上锁使用lock(),解锁使用unlock()。
由于需要手动解锁,触发 return 或者 异常时 容易忘记解锁,为了避免这种问题,正确使用 ReenactmentLock 时需要把 unlock 操作放到 finally 中。

问题:既然有 synchronized,为啥还要用 ReenactmentLock ?(面试题)

1、ReenactmentLock 提供了 tryLock 操作。

  • lock 尝试进行加锁,如果加锁不成,就会阻塞;
  • tryLock 尝试进行加锁,如果加锁不成,不阻塞,直接返回 false;(更多的可操作空间)

2、ReenactmentLock 提供了公平锁的实现,通过队列记录加锁线程的先后顺序。

3、搭配的等待通知机制不同。

  • 对于 synchronized,搭配 wait/notify
  • 对于 ReenactmentLock,搭配 Condition 类,功能比 wait/notify 略强一些

1.3、Semaphore 信号量

首先举例说明 semaphore 信息量的概念:停车场入口立着的那个显示屏,每有一辆车进入停车场显示屏就会显示剩余车位减1,每有一辆车从停车场出去,显示屏上显示的剩余车辆就会加1,当显示屏上的剩余车位为0时,停车场入口的栏杆就不会再打开,车辆就无法进入停车场了,直到有一辆车从停车场出去为止。

而这个场景中提及的“显示屏”这个东西,就可以认为是信息量,表示“可用资源的个数”,申请一个可用资源,就会使数字 - 1,这个操作就成为 p 操作,释放一个可用资源,就会使数字 + 1,这个操作就是 v 操作,如果信息量数值为 0,继续 p 操作就会进行阻塞。

信号量是更广义的“锁”。所谓锁,本质上也是一种特殊的信息量,可以把锁认为是计数值为 1 的信息量。释放状态,就是1,加锁状态就是0,对于这种非0即1的信息量,称为“二元信息量”。除此之外,同样 Semaphore 也可以用来实现生产者消费者模型

acquire() 表示申请资源(P操作);
release() 表示释放资源(V操作);

使用 semaphore 模式锁并使用模拟锁实现两个线程同时对 i 自增 5w 的操作

package thread;

import java.util.concurrent.Semaphore;

public class ThreadDemo38 {
    private static int count = 0;

    public static void main(String[] args) throws InterruptedException {
        //信息量设置为 1
        Semaphore semaphore = new Semaphore(1);

        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 50000; i++) {
                try {
                    semaphore.acquire();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                count++;
                semaphore.release();
            }
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 50000; i++) {
                try {
                    semaphore.acquire();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                count++;
                semaphore.release();
            }
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();

        System.out.println("count = " + count);
    }
}

1.4、CountDownLatch

针对特定场景下解决问题的小工具。作用:同时等待 N 个任务执行结束。

比如,多线程执行一个任务,把大的任务拆分成几个部分,由每个线程分别执行。“多线程下载”:idm,比特彗星

package thread;

import java.util.Random;
import java.util.concurrent.CountDownLatch;

public class ThreadDemo39 {
    public static void main(String[] args) throws InterruptedException {
        // 1. 此处构造方法中写 10, 意思是有 10 个线程/任务
        CountDownLatch latch = new CountDownLatch(10);

        // 创建出 10 个线程负责下载.
        for (int i = 0; i < 10; i++) {
            int id = i;
            Thread t = new Thread(() -> {
                Random random = new Random();
                // [0, 5)
                int time = (random.nextInt(5) + 1) * 1000;
                System.out.println("线程 " + id + " 开始下载");
                try {
                    Thread.sleep(time);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("线程 " + id + " 结束下载");
                // 2. 告知 countDownLatch 我执行结束了.
                latch.countDown();
            });
            t.start();
        }

        // 3. 通过这个 await 操作来【等待所有任务结束】. 也就是 countDown 被调用 10 次了.
        latch.await();
        System.out.println("所有任务都已经完成了!");
    }
}
  • 每个任务执行完毕,都调用 latch.countDown()。在 CountDownLatch 内部的计数器同时自减。
  • 主线程中使用 latch.await(); 阻塞等待所有任务执行完毕,相当于计数器为 0 了。

【博主推荐】 

【网络原理】TCP 协议中比较重要的一些特性(三)-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/zzzzzhxxx/article/details/136597348?spm=1001.2014.3001.5501【Java多线程】关于多线程的一些案例 —— 单例模式中的饿汉模式和懒汉模式以及阻塞队列-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/zzzzzhxxx/article/details/136688859?spm=1001.2014.3001.5501【网络原理】TCP 协议中比较重要的一些特性(二)-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/zzzzzhxxx/article/details/136579333?spm=1001.2014.3001.5501

如果觉得作者写的不错,求给博主一个大大的点赞支持一下,你们的支持是我更新的最大动力!

如果觉得作者写的不错,求给博主一个大大的点赞支持一下,你们的支持是我更新的最大动力!

如果觉得作者写的不错,求给博主一个大大的点赞支持一下,你们的支持是我更新的最大动力!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

电机学(笔记一)

磁极对数p&#xff1a; 直流电机的磁极对数是指电机定子的磁极对数&#xff0c;也等于电机电刷的对数。它与电机的转速和扭矩有直接关系。一般来说&#xff0c;极对数越多&#xff0c;电机转速越低&#xff0c;扭矩越大&#xff0c;适用于低速、高扭矩的场合&#xff1b;相反&…

MATLAB的使用(一)

一&#xff0c;MATLAB的编程特点 a,语法高度简化&#xff1b; b,脚本式解释型语言&#xff1b; c,针对矩阵的高性能运算&#xff1b; d,丰富的函数工具箱支持&#xff1b; e,通过matlab本体构建跨平台&#xff1b; 二&#xff0c;MATLAB的界面 工具栏:提供快捷操作编辑器…

HCIP的学习(2)

TCP----传输控制协议 是一种面向连接的可靠传输协议。 注&#xff1a;与我之前博客HCIA的学习&#xff08;2&#xff09;结合一起看 面向连接&#xff1a;数据传输前收发双方建立一条逻辑通路 特点&#xff1a; TCP是一种面向连接的传输协议每一条TCP连接有且只能存在两个端…

kafka2.x版本配置SSL进行加密和身份验证

背景&#xff1a;找了一圈资料&#xff0c;都是东讲讲西讲讲&#xff0c;最后我还没搞好&#xff0c;最终决定参考官网说明。 官网指导手册地址&#xff1a;Apache Kafka 先只看SSL安全机制方式。 Apache Kafka 允许客户端通过 SSL 进行连接。默认情况下&#xff0c;SSL 处于…

婴儿专用洗衣机哪个牌子比较好?热诚安利五大出类拔萃婴儿洗衣机

婴儿洗衣机可以用于单独清洗宝宝的衣物&#xff0c;可以有效避免了与大人衣物一起混洗带来的细菌交叉感染。毕竟&#xff0c;在婴儿吃奶或者接触其他材料时&#xff0c;其抵抗力是比较弱的&#xff0c;再加上普通洗衣机无法对婴儿的衣物进行有效的消毒处理&#xff0c;轻则会对…

SpringCache和redis区别?什么是SpringCache?

目录 一、Redis介绍1.1 Redis缓存1.2 redis缓存使用前提1.3 redis使用缓存的时机 二、实际操作案例2.1 常规准备工作2.2 引入配置redis2.2.1 引入redis的启动依赖2.2.2 在application.yml里面配置redis的地址信息等2.2.3 创建redisTemplate的配置类&#xff0c;指定键值序列化方…

探索区块链世界:从加密货币到去中心化应用

相信提到区块链&#xff0c;很多人会想到比特币这样的加密货币&#xff0c;但实际上&#xff0c;区块链技术远不止于此&#xff0c;它正在深刻地改变我们的生活和商业。 首先&#xff0c;让我们来简单了解一下什么是区块链。区块链是一种分布式数据库技术&#xff0c;它通过将…

Linux docker1--环境及docker安装

一、基础环境要求 Docker分为ce版本&#xff08;免费&#xff0c;试用7个月&#xff09;和ee版本&#xff08;收费&#xff09;。 最低配置要求&#xff1a;64位操作系统&#xff0c;centOS 7及以上&#xff0c;内核版本不低于3.10 二、部署docker 1、查看服务的基础环境是否满…

MVC接收请求教程

mvc接收各种请求 1-环境搭建 1.1-准备apifox发送请求 1.2-项目搭建 ①创建Web骨架的Maven项目 ​ --打开2023-IDEA &#xff0c;选择New Project ​ --选择Maven Archetype ​ --注意点&#xff1a;Catalog默认就行了 ​ --Archetype选择webapp ​ --JDK跟着黑马敲最好…

情感书单图片怎么制作?书单制作教程分享

情感书单图片怎么制作&#xff1f;情感书单图片制作是一项富有创意和挑战性的任务&#xff0c;它要求我们不仅要有对书籍的热爱&#xff0c;还要有一定的审美和设计能力。幸运的是&#xff0c;现在市面上有许多专业的软件可以帮助我们实现这一目标&#xff0c;让情感书单图片的…

好书推荐 《ARM汇编与逆向工程 蓝狐卷 基础知识》

《ARM 汇编与逆向工程 蓝狐卷 基础知识》 与传统的 CISC&#xff08;Complex Instruction Set Computer&#xff0c;复杂指令集计算机&#xff09;架构相比&#xff0c;Arm 架构的指令集更加简洁明了&#xff0c;指令执行效率更高&#xff0c;能够在更低的功耗下完成同样的计…

并发编程Semaphore(信号量)浅析

目录 一、简介二、API三、使用3.1 demo13.1 demo2 四、适用场景 一、简介 Semaphore&#xff08;信号量&#xff09;是 Java 中用于控制同时访问特定资源的线程数量的工具类。Semaphore 维护了一组许可证&#xff0c;线程在访问资源之前必须先获取许可证&#xff0c;访问完毕后…

【ADF4351】使用FPGA进行SPI寄存器配置、使用FPGA计算各个频率的频点,ADF4351配置程序

简介 特性 输出频率范围&#xff1a;35 MHz至4,400 MHz 小数N分频频率合成器和整数N分频频率合成器 具有低相位噪声的VCO 可编程的1/2/4/8/16/32/64分频输出 典型抖动&#xff1a;0.3 ps rms EVM(典型值&#xff0c;2.1 GHz)&#xff1a; 0.4% 电源&#xff1a;3.0 V至3.6 V …

Acwing.2060 奶牛选美(DFS)

题目 听说最近两斑点的奶牛最受欢迎&#xff0c;约翰立即购进了一批两斑点牛。 不幸的是&#xff0c;时尚潮流往往变化很快&#xff0c;当前最受欢迎的牛变成了一斑点牛。 约翰希望通过给每头奶牛涂色&#xff0c;使得它们身上的两个斑点能够合为一个斑点&#xff0c;让它们…

构建卓越数据应用体系,释放企业数据资产的最大价值

随着数字化浪潮的汹涌而至&#xff0c;数据已经成为驱动社会发展的重要资源。在这个信息爆炸的时代&#xff0c;如何有效地收集、管理、分析和应用数据&#xff0c;成为摆在我们面前的一大挑战。数据应用体系的建设&#xff0c;不仅关乎企业竞争力的提升&#xff0c;更是推动整…

前端模块化开发

模块化发展历程 一个模块单独抽离成一个文件&#xff0c;&#xff08;缺点&#xff1a; 命名冲突&#xff0c;全靠约定&#xff09;命名空间的方式&#xff0c;导出一个对象&#xff08;确定&#xff1a;命名冲突还是存在&#xff0c;可在外部修改&#xff0c;没解决依赖关系的…

fastadmin实验教学管理最近新增功能的技术盘点

在与用户交流中&#xff0c;发现了有些功能不够便捷&#xff0c;特抽出时间优化了一下 一键锁定 优化背景&#xff1a;先通过实验日期或实验名称先搜索&#xff0c;然后选中对应的复选框&#xff0c;再点击“锁定”&#xff0c;这样容易漏选或错选 1.工具栏新增自定义按钮“一…

目标检测——PP-YOLOv2算法解读

PP-YOLO系列&#xff0c;均是基于百度自研PaddlePaddle深度学习框架发布的算法&#xff0c;2020年基于YOLOv3改进发布PP-YOLO&#xff0c;2021年发布PP-YOLOv2和移动端检测算法PP-PicoDet&#xff0c;2022年发布PP-YOLOE和PP-YOLOE-R。由于均是一个系列&#xff0c;所以放一起解…

面向未来的前沿人工智能监管

策制定者应该为未来十年人工智能系统更加强大的世界做好准备。这些发展可能会在人工智能科学没有根本性突破的情况下发生&#xff0c;只需扩展当今的技术以在更多数据和计算上训练更大的模型即可。 用于训练前沿人工智能模型的计算量在未来十年可能会显着增加。到 2020 年代末…

Linux初识环境变量

&#x1f30e;环境变量【上】 文章目录&#xff1a; 环境变量 什么是环境变量 关于命令行参数 环境变量       简单了解       为什么需要环境变量       系统中其他环境变量 总结 前言&#xff1a; 环境变量是一种非常重要的概念&#xff0c;它们对于系统的…