JUC下常见类

news2024/12/25 1:17:42

    • JUC(java.util.concurrent) 的常见类
      • ReentrantLock
      • 原子类
      • 线程池
      • 信号量Semaphore
      • CountDownLatch

JUC(java.util.concurrent) 的常见类

ReentrantLock

ReentrantLock可重入互斥锁. 和 synchronized 定位类似, 都是用来实现互斥效果, 保证线程安全。
用法:
lock(): 加锁, 如果获取不到锁就死等.
trylock(超时时间): 加锁, 如果获取不到锁, 等待一定的时间之后就放弃加锁.
unlock(): 解锁

ReentrantLock lock = new ReentrantLock(); 
lock.lock();   
	try {    
 // working    
} finally {    
 lock.unlock() //得注意要用finally解锁保证能执行到;避免中间返回了;后面没解锁。   它里面有一个返回值判断的;加锁成功就后面会执行这个解锁代码;否则不执行解锁逻辑。
} 

为什么有synchronized还要ReentrantLock?
synchronized 在申请锁失败时, 会死等. ReentrantLock 可以通过 try lock 的方式等待一段时间就放弃
synchronized 是非公平锁, ReentrantLock 默认是非公平锁. 可以通过构造方法传入一个 true 开启公平锁模式
更强大的唤醒机制:synchronized可以搭配Object 的 wait / notify 实现等待-唤醒。 每次唤醒的是一个随机等待的线程。 ReentrantLock 搭配 Condition 类实现等待-唤醒, 可以更精确控制唤醒某个指定的线程。

原子类

在这里插入图片描述

线程池

ThreadPoolExecutor线程池描述;有3个重载方法最少5个参数最多7个参数描述
1:int corePoolsize。你可以理解是一个正式员工;核心线程数
2:maximumPoolsize;最大线程数;正式员工+实习生(临时线程)
3:long keepAliveTime;实习生摸鱼时间;
4:TimeUnit unit,;描述实习生摸鱼的最长时间;超过这个时间就给它开除掉。
5:BlockinBoueue workQueue;描述这个任务队列是阻塞的还是非阻塞的;是有界的还是无界的。无界就是存的任务是无限的。有界的就是存的任务量有限;超过了就执行执行拒绝策略。我们通常设置阻塞无界。
6:threadFactory; 表示线程的创建工厂。用的比较少;一般但是使用默认的线程创建工厂的方法来创建线程。你可以设置创建线程的类型(前台、后台)、优先级、命名。
7:RejectedExecutionHandler;表示指定线程池的拒绝策略。当任务队列满了不能再创建新线程执行此任务就会使用该拒绝策略

创建线程池的方式: Executors是一个线程工厂;Executors 本质上是 ThreadPoolExecutor 类的封装。让我们创建更方便;无需去设置那么多参数。
在这里插入图片描述
1:创建核心线程和最大线程一致线程池
ExecutorService executorService = Executors.newFixedThreadPool(5);
源代码如下:

public static ExecutorService newFixedThreadPool(int nThreads) { 
     return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()); }

2:创建核心线程大小和最大线程数为1的线程池
ExecutorService executorService = Executors.newSingleThreadExecutor();
源代码如下:重载方法ThreadFactory 的参数;传入我们自定义的线程创建工厂,如果不传入则会调用默认的线程工厂;线程工厂就是用来设置线程其它特性;比如优先级、命名、类型

public static ExecutorService newSingleThreadExecutor() { 
      return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new   LinkedBlockingQueue())); 
   } 
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) { 
      return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new                   LinkedBlockingQueue(), threadFactory)); }

永远只有一个线程处理任务;适用于所有任务都需要按被提交的顺序来执行的场景,是个单线程的串行。

3:创建核心线程大小为0;最大线程大小Integer.MAX_VALUE线程池
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
源代码如下:默认情况最大线程数为 Integer.MAX_VALUE , 意味着他的线程数几乎可以无限增加。创建的线程都是临时线程,所以他们都会被销毁,这里空闲 线程销毁时间是60秒,也就是说当线程在60秒内没有任务执行则销毁。使用SynchronousQueue 的一个阻塞队列;它只能存一个任务;当一个任务存就来其它任务想存进来就会阻塞等待这个原任务被消费;它的意义不是储存的;而是在与传递的场景;任务消费很快。适用的场景效率就会高;因为没有核心线程一直占用资源;没有任务60秒后就销毁。

public static ExecutorService newCachedThreadPool() { 
       return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue()); } 
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) { 
       return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue(), threadFactory); }

4:创建线程池定时或者周期性执行任务
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
线程总大小为 3,但核心线程数是 0,线程池会根据任务的需要动态创建线程。
源码如下:

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
     return new ScheduledThreadPoolExecutor(corePoolSize); }
public static ScheduledExecutorService newScheduledThreadPool( int corePoolSize, ThreadFactory threadFactory) {
     return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory); }

利用这个线程池可以设定延迟时间后执行命令,或者定期执行命令. 是进阶版的 Timer

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
// 延迟 2 秒后执行任务
scheduledThreadPool.schedule(() -> {
    System.out.println("Task executed after 2 seconds");
}, 2, TimeUnit.SECONDS);

// 初始延迟 2 秒,之后每隔 3 秒执行一次任务
//scheduleAtFixedRate 方法用于定期执行任务,无论上一个任务是否执行完成。
scheduledThreadPool.scheduleAtFixedRate(() -> {
    System.out.println("Task executed at fixed rate");
}, 2, 3, TimeUnit.SECONDS);


// 初始延迟 2 秒,之后每次任务执行完成后延迟 3 秒再执行下一个任务
//scheduleWithFixedDelay 方法用于定期执行任务,确保上一个任务完成后,间隔固定的时间再执行下一个任务。
scheduledThreadPool.scheduleWithFixedDelay(() -> {
    System.out.println("Task executed with fixed delay");
}, 2, 3, TimeUnit.SECONDS);

5:上述都是线程工厂类创建的;封装各种线程池的创建方式。ThreadPoolExecutor 提供了更多的可选参数, 可以进一步细化线程池行为的设定.

import java.util.concurrent.*;

public class CustomThreadPoolExample {
    public static void main(String[] args) {
        // 1. 核心线程池大小
        int corePoolSize = 5;

        // 2. 最大线程池大小
        int maximumPoolSize = 10;

        // 3. 线程空闲时间
        long keepAliveTime = 60; // 60 秒

        // 4. 空闲时间的单位
        TimeUnit unit = TimeUnit.SECONDS;

        // 5. 任务队列,这里使用 LinkedBlockingQueue
        BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>();

        // 6. 线程工厂
        ThreadFactory threadFactory = Executors.defaultThreadFactory();

        // 7. 拒绝策略,这里使用默认的 AbortPolicy
        RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();

        // 创建 ThreadPoolExecutor
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                keepAliveTime,
                unit,
                workQueue,
                threadFactory,
                handler
        );

        // 提交任务
        executor.submit(() -> {
            System.out.println("Task executed by the custom thread pool");
        });

        // 关闭线程池
        executor.shutdown();
    }
}

信号量Semaphore

信号量, 用来表示 “可用资源的个数”. 本质上就是一个计数器;Semaphore 的acquire 方法申请资源(–操作), release 方法释放资源(++操作), 原子性可以在多线程环境下直接使用。如果计数器的值已经为 0 了, 还尝试申请资源, 就会阻塞等待, 直到有其他线程释放资源。
Semaphore semaphore = new Semaphore(4);
semaphore.acquire();//申请资源
semaphore.release();//释放资源

CountDownLatch

等待任务结束的效果: CountDownLatch latch = new CountDownLatch(10);初始化 10 表示有 10 个任务需要完成。然后你每个任务完成都能调用一下latch.countDown() (原子性–操作)。你在主线程latch.await(); 阻塞等待所有任务执行完毕;相当于计数器为 0 了。

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

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

相关文章

合同审查---财务条款、合同形式与生效审查

1.合同主体 1人 廖 2.财务条款、合同形式与生效 1人 黄 3.履行、验收、知识产权、不可抗力 1人 詹 4.违约责任、争议解决、保密、法律引用 1人 王 代码规范&#xff1a; 1.代码函数的层级 各审查点在json中分为3级层级&#xff0c;但用python写规则的时候&#xff0c;1级层级为…

【C++那些事儿】类与对象(2)

君兮_的个人主页 即使走的再远&#xff0c;也勿忘启程时的初心 C/C 游戏开发 Hello,米娜桑们&#xff0c;这里是君兮_&#xff0c;我之前看过一套书叫做《明朝那些事儿》&#xff0c;把本来枯燥的历史讲的生动有趣。而C作为一门接近底层的语言&#xff0c;无疑是抽象且难度颇…

LeetCode 面试题 16.20. T9键盘

文章目录 一、题目二、C# 题解 一、题目 在老式手机上&#xff0c;用户通过数字键盘输入&#xff0c;手机将提供与这些数字相匹配的单词列表。每个数字映射到0至4个字母。给定一个数字序列&#xff0c;实现一个算法来返回匹配单词的列表。你会得到一张含有有效单词的列表。映射…

图书销售数据大屏可视化【可视化项目案例-03】

🎉🎊🎉 你的技术旅程将在这里启航! 🚀🚀 本文选自专栏:可视化技术专栏100例 可视化技术专栏100例,包括但不限于大屏可视化、图表可视化等等。订阅专栏用户在文章底部可下载对应案例源码以供大家深入的学习研究。 🎓 每一个案例都会提供完整代码和详细的讲解,不…

Leetcode-144 二叉树的前序遍历

递归方法 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, TreeNode right) {* …

谈谈如何写作(一)

序言 没有什么比一套好理论更有用了。——库尔特勒温 谈谈如何写作&#xff1f; 这个题目就像一本书《如何阅读一本书》&#xff0c;听起来似乎很无趣&#xff0c;因为各位盆友直接的反应&#xff0c;可能是这根本无需理论。 实际情况呢&#xff1f;恰恰相反&#xff0c;往往你…

javax.management.InstanceNotFoundException: Catalina:type=Server错误的解决

软件&#xff1a; JDK 1.8 Tomcat 8.5.66 IDEA 2019.3.3 问题&#xff1a;启动IDEA新建一Web Application项目&#xff0c;设置好项目运行&#xff0c;结果发现提示&#xff1a; 提示&#xff1a;Application Server was not connected before run configuration stop, rea…

JavaSE 类与对象

前言 我们之前学的都是面向过程&#xff0c;面向过程研究的是对单个对象的一种方法实现过程&#xff0c;比如求一个数的阶乘&#xff0c;强调的是怎么实现这个方法的过程&#xff0c;但对我们以后来说&#xff0c;如果想要应用到更广的层面&#xff0c;不能只是学习一个方法的…

基于Qt Linux开发板USER-KEY按键实现

介绍如何在 Qt 应用上使用嵌入式 GET6818 Linux 开发板 上的按键。 工具:Qt Creator 5.14.2 平台:windows ## 资源简介 在GET6818 开发板,开发板板载资源上有两个用户按键。如下图原理图(下图开发板的按键原理图)。 ## 应用实例 想要监测这个 KEY0,首先出厂内核已经…

Linux是什么,Linux系统介绍

很多小伙伴都不是那么了解和知道Linux&#xff0c;到底Linux是什么&#xff1f; 像大家用到的安卓手机&#xff0c;生活中用到的各种智能设备&#xff0c;比如路由器&#xff0c;光猫&#xff0c;智能家具等&#xff0c;很多都是在Linux操作系统上。 Linux是什么&#xff1f;Li…

常见问题: (Windows/app/浏览器)总结及其研究———(不断更新中.....)

问题目录 手机电脑电脑qq如何多开分身电脑与手机无线传送数据的方法 浏览器下载如何利用技术下载网上图片 WindowsVMware Workstation1 无法创建11264MB的匿名分页文件&#xff1a;页面文件2 虚拟机安装Windows11时出现: tempting to start up from: EFI VMware Virtual N 百度…

Vuex:模块化Module :VCA模式

VCA中不支持辅助函数&#xff0c;因为辅助函数中是用this.$store&#xff0c;而VCA中没有绑定this的 由于使用单一状态树&#xff0c;应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时&#xff0c;store 对象就有可能变得相当臃肿。 这句话的意思是&#xff0c;…

开源Gimp动态压感笔刷设置方法

一、问题描述 开源绘画工具的Gimp的笔刷压感在哪里控制和开启呢&#xff1f; 二、解决方法 1、Gimp有专用的笔刷集&#xff1a;如下图。开启需要在主窗口window下拉菜单开启&#xff0c;或在右侧面板里的左箭头按钮里打开。一般绘画够用了。比用自定义特殊笔刷。 2、如果要调…

win11系统提示msvcp140.dll丢失的解决方法,3个有效的解决方法

Win11系统在运行photoshop或其他软件&#xff0c;游戏的时候&#xff0c;电脑提示“找不到msvcp140.dll”&#xff0c;“msvcp140.dll丢失”&#xff0c;“无法定位输入点msvcp140.dll”等问题&#xff0c;都是由于Windows11系统中的msvcp140.dll文件丢失或者损坏了。 一、问题…

【开源】基于Vue.js的大学兼职教师管理系统的设计和实现

目录 一、摘要1.1 项目介绍1.2 项目详细录屏 二、研究内容三、界面展示3.1 登录注册3.2 学生教师管理3.3 课程管理模块3.4 授课管理模块3.5 课程考勤模块3.6 课程评价模块3.7 课程成绩模块3.8 可视化图表 四、免责说明 一、摘要 1.1 项目介绍 大学兼职教师管理系统&#xff0…

HTTP-FLV详解及分析

文章目录 前言一、HTTP-FLV 简介1、市场上使用 http-flv 的商家2、http-flv、rtmp 和 hls 直播的优缺点3、http-flv 技术实现 二、Nginx 配置 http-flv1、Windows 安装 nginx&#xff0c;已经集成 nginx-http-flv-module2、nginx.conf 配置文件3、运行 nginx 服务器4、ffmpeg 推…

Linux系统编程——文件操作原理

文件描述符 1.文件描述符是文件的索引&#xff1a; 对于内核而言&#xff0c;所有打开文件都由文件描述符引用。文件描述符是一个非负整数。当打开一个现存文件或者创建一个新文件时&#xff0c;内核向进程返回一个文件描述符。 int fd1 open("./file1",O_RDWR);…

【C++初阶】二、入门知识讲解(引用、内联函数、auto关键字、基于范围的for循环、指针空值nullptr)

相关代码gitee自取&#xff1a; C语言学习日记: 加油努力 (gitee.com) 接上期&#xff1a; 【C初阶】一、入门知识讲解 &#xff08;C关键字、命名空间、C输入&输出、缺省参数、函数重载&#xff09;-CSDN博客 六 . 引用 &#xff08;1&#xff09;. 引用的概念和特性…

内存管理

目录 C/C内存分布 引入 分析 说明 C语言内存管理方式&#xff1a;malloc calloc realloc free malloc realloc calloc 面试题 C内存管理方式 new/delete操作符 用法 new和delete操作自定义类型 operator new和operator delete函数 operator new ​编辑 operator…

什么是Ribbon的饥饿加载?有什么优势?

目录 一、什么是Ribbon 二、什么是饥饿加载 三、Ribbon饥饿加载的优势 四、Ribbon饥饿加载的劣势 一、什么是Ribbon Ribbon是一个开源的、基于HTTP和TCP的客户端负载均衡工具&#xff0c;它提供了一个简单的、基于配置的负载均衡策略&#xff0c;可以帮助开发人员更轻松地…