JUC的常见类

news2024/11/25 4:46:25

Callable interfacce

也是一种创建线程的方式
Runnable 能表示一个任务(run方法),返回void
Callable 也能表示一个任务(call方法),返回一个具体的值,类型可以通过泛型参数来指定(object)
如果进行多线程操作,如果你只是关心多线程的执行过程,使用Runnable即可,如果是关心多线程的计算结果,使用Callable更合适
使用Callable不能直接作为Thread的构造方法参数,我们可以借用FutureTask来完成
,运算的结果什么时候能算出来,可以使用FutureTask来帮助我们解决这个问题

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class demo2 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Callable<Integer> callable = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                int sum =0;
                for (int i =0;i<1000;i++){
                    sum +=i;
                }
                return sum;
            }
        };
        FutureTask<Integer> futureTask =new FutureTask<>(callable);
        Thread t1 =new Thread(futureTask);
        t1.start();
        //获取call方法返回的结果,get类似于join,如果call方法没有执行完,就会阻塞等待
        Integer result = futureTask.get();
        System.out.println(result);
    }
}

在这里插入图片描述

ReentrantLock

可重入互斥锁. 和 synchronized 定位类似, 都是用来实现互斥效果, 保证线程安全.

ReentrantLock 的用法:
lock(): 加锁, 如果获取不到锁就死等.
trylock(超时时间): 加锁, 如果获取不到锁, 等待一定的时间之后就放弃加锁.
unlock(): 解锁
虽然synchronized也是一个可重入锁,但是这两者还是又明显的区别的

ReentrantLock的优点

1.提供了一个trylock的方法进行加锁
对于lock操作来说,如果加锁不成功,就会出现阻塞等待(死等).
对于trylock,如果加锁失败,直接返回false/也可以设定等待时间,该方法给锁操作提供了更多的可操作空间
2.有两种模式,可以工作在公平锁的状态下,也可以工作在非公平锁的状态下,构造方法中可以通过参数设定的公平/非公平模式
3.也有一个等待通知机制,搭配condition这样的类来完成,这里的等待要比wait notify功能更强

ReentrantLock的缺点

unlock()解锁方法容易被人忘记,常常需要搭配finally来使用
synchronized的锁对象可以是任意对象
ReentrantLock的锁对象就只能是自己本身,如果多个线程针对不同的ReentrantLock调用lock方法,此时是不会产生锁竞争的

原子类

原子类内部用的是 CAS 实现,所以性能要比加锁实现 i++ 高很多。原子类有以下几个

AtomicBoolean
AtomicInteger
AtomicIntegerArray
AtomicLong
AtomicReference
AtomicStampedReference

以 AtomicInteger 举例,常见方法有

addAndGet(int delta); i += delta;
decrementAndGet(); --i;
getAndDecrement(); i–;
incrementAndGet(); ++i;
getAndIncrement(); i++;
(具体可看CAS详解)

线程池

虽然创建销毁线程比创建销毁进程更轻量, 但是在频繁创建销毁线程的时候还是会比较低效.
线程池就是为了解决这个问题. 如果某个线程不再使用了, 并不是真正把线程释放, 而是放到一个 “池子”
中, 下次如果需要用到线程就直接从池子中取, 不必通过系统来创建了.
(具体可看线程池详解)

信号量Semaphore

在操作系统中,也经常出现,是并发编程的一个重要的概念/组件
准确来说,Semaphore是一个计数器(变量),描述了"可用资源的个数",描述的是,当前这个线程,是否有"临界"资源可以用,所谓的临界资源,是指的多个线程/进程等并发执行的实体可以公共使用到的资源(多个线程修改同一个变量,这个变量就可以被认为是一个临界资源)

示例

停车场景:
停车场的入口,上面会挂这一个显示屏,上面会显示停车场内可用的车位
如果开车进入停车场,申请一个车位(申请了一个可用资源),此时计数器就会+1,称为p操作
如果开车离开停车场,释放了一个车位(释放了一个可用资源),此时计数器就会-1,称为v操作
如果发现车位计数器上面的计数器为0,这个时候,有两种选择:
1.等
2.放弃,寻找下个车位
这里我们选择第一种操作,继续进行p操作,就会阻塞等待,一直等到其他车辆进行了v操作,释放了一个空闲的车位为止,
锁,本质上是一个特殊的信号量(里面的数值,非0即1,二元信号量),信号量要比锁更广义,不仅仅可以描述一个资源,还可以描述N个资源,虽然概念上更广泛,实际开发中,还是锁更多一些(二元信号量的场景是更常见的)

package Thread;

import java.util.concurrent.Semaphore;

public class demo3 {
    public static void main(String[] args) throws InterruptedException {
        //构造方法中,就可以用来指定计数器的初始值
        Semaphore semaphore = new Semaphore(4);
        semaphore.acquire();//计数器-1
        System.out.println("执行p操作");
        semaphore.acquire();//计数器-1
        System.out.println("执行p操作");
        semaphore.acquire();//计数器-1
        System.out.println("执行p操作");
        semaphore.acquire();//计数器-1
        System.out.println("执行p操作");
        semaphore.acquire();//计数器-1
        System.out.println("执行p操作");
    }
}

在这里插入图片描述

CountDownLatch

同时等待n个任务执行结束

好像跑步比赛,10个选手依次就位,哨声响才同时出发;所有选手都通过终点,才能公布成绩

构造 CountDownLatch 实例, 初始化 10 表示有 10 个任务需要完成.
每个任务执行完毕, 都调用 latch.countDown() . 在 CountDownLatch 内部的计数器同时自减.
主线程中使用 latch.await(); 阻塞等待所有任务执行完毕. 相当于计数器为 0 了.

package Thread;

import java.util.concurrent.CountDownLatch;

public class demo1 {
    public static void main(String[] args) throws InterruptedException {
    //相当于创建一个线程任务为10的计数器
        CountDownLatch countDownLatch = new CountDownLatch(10);
        for (int i = 0;i<10;i++){
        //防止因为变量捕获的机制使得无法正常访问i变量
            int id =i;
            Thread t = new Thread(()->{
                System.out.println("线程"+id+"开始工作");
                try {
                    //使用sleep来代指某些耗时操作
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程"+id+"结束工作");
                //每次调用countDown就相当于使得计数器减一
                countDownLatch.countDown();
            });
            t.start();
        }
        //如果计数器没有减到0,就会进入阻塞等待
        countDownLatch.await();
        System.out.println("多个线程的所有任务都执行完毕");
    }
}

在这里插入图片描述

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

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

相关文章

Lottery抽奖项目第二章第二节:搭建DDD四层结构

搭建DDD四层结构 DDD&#xff1a;Domain Driven Design 描述&#xff1a;基于DDD架构构建&#xff0c;初始化搭建工程结构 本节是陆续搭建系统和编码的开始&#xff0c;我们会优先完成一个基础工程的创建。一般在互联网企业这部分工作可能不需要反复处理&#xff0c;只需要在…

自然语言处理(二):近似训练

近似训练 近似训练&#xff08;Approximate Training&#xff09;是指在机器学习中使用近似的方法来训练模型&#xff0c;以降低计算复杂度或提高训练效率。这种方法通常用于处理大规模数据集或复杂模型&#xff0c;其中精确的训练算法可能过于耗时或计算资源不足。 近似训练…

14张图带你了解Android14中的酷炫的功能

14张图带你了解Android14中的酷炫的功能 在近期的几次更新中&#xff0c;Android系统经历了重要的升级。Android 12通过Material UI改变了外观&#xff0c;使界面更加优化。随后&#xff0c;Android 13在Android 12的基础上进一步提升了用户体验&#xff0c;使系统更加流畅。现…

自己的第一个小程序《我们一起记账吧》

一&#xff0c;想法 为了控制自己不要乱花钱&#xff0c;曾经一段时间每天记账&#xff0c;当时用的是市面上比较受欢迎的一些记账工具&#xff0c;但大多数都是以个人角度来记账的&#xff0c;几乎没有以家庭为单位的多人协同记账类软件&#xff0c;虽然也有多人记账小程序&a…

7.11 SpringBoot实战 全局异常处理 - 深入细节详解

文章目录 前言一、异常分类1.1 业务异常1.2 参数校验异常1.3 通用异常兜底 二、保留异常现场2.1 请求地址2.2 请求header2.3 请求参数body2.4 构建异常上下文消息 最后 前言 全局异常处理, 你真的学会了吗&#xff1f; 学完上文&#xff0c;你有思考和动手实践吗&#xff1f;…

stm32之25.FLASH闪存

打开标准库 源码--- int main(void) {uint32_t d;Led_init();key_init();/* 初始化串口1波特率为115200bps&#xff0c;若发送/接收数据有乱码&#xff0c;请检查PLL */usart1_init(115200);printf("this is flash test\r\n");/* 解锁FLASH&#xff08;闪存&#xf…

腾讯云服务器搭建网站详细教程_2023更新

使用腾讯云服务器搭建网站全流程&#xff0c;包括轻量应用服务器和云服务器CVM建站教程&#xff0c;轻量可以使用应用镜像一键建站&#xff0c;云服务器CVM可以通过安装宝塔面板的方式来搭建网站&#xff0c;腾讯云服务器网分享使用腾讯云服务器建站教程&#xff0c;新手站长搭…

系统架构设计高级技能 · Web架构

现在的一切都是为将来的梦想编织翅膀&#xff0c;让梦想在现实中展翅高飞。 Now everything is for the future of dream weaving wings, let the dream fly in reality. 点击进入系列文章目录 系统架构设计高级技能 Web架构 一、Web架构介绍1.1 Web架构涉及技术1.2 单台服务…

几个nlp的小任务(生成任务(摘要生成))

几个nlp的小任务生成任务——摘要生成 安装库选择模型加载数据集展示数据集数据预处理 tokenizer注意特殊的 token处理组成预处理函数调用map,对数据集进行预处理微调模型,设置参数设置数据收集器,将处理好的数据喂给模型封装测评方法将参数传给 trainer,开始训练安装库 选…

交叉熵的简单理解:真实分布与非真实分布的交叉,完全对应,熵为0

目录 交叉熵的简单理解&#xff1a;真实分布与非真实分布的交叉&#xff0c;完全对应&#xff0c;熵为0 交叉熵的简单理解&#xff1a;真实分布与非真实分布的交叉&#xff0c;完全对应&#xff0c;熵为0 这个式子就是熵的表达式. 简单来说, 其意义就是在最优化策略下, 猜到颜…

哪些自主品牌「霸榜」30万元向上战场?硬派越野/MPV再助力

占乘用车市场不到20%份额的30万元以上价位&#xff0c;一直以来都是合资品牌的天下。现在&#xff0c;三家中国本土自主品牌已经率先突围。 高工智能汽车研究院监测数据显示&#xff0c;2023年1-7月&#xff0c;理想、比亚迪、蔚来进入30万元以上价位新车交付量TOP10&#xff…

c++系列之指针

今天不是做题系列&#xff0c;是知识系列啦。 说到指针&#xff0c;我们初学这一定会气的牙痒痒把&#xff0c;笔者也是&#xff0c;这么我好久而不得呀&#xff0c;今天来让我们聊聊指针。 其一 首先&#xff0c;我们明确的知道&#xff0c;假如我们开一个变量&#xff0c;…

Android studio 软件git使用

在 test 分支添加的方法 , 现在切换到 master分支 总共 2 个分支 , 当前的分支是 test 出现了 先试一下 force checkout , 尝试之后发现 , 你更改没有带过来 , 以为哪个类在master分支没有 , 所以这边也没有 , 切回分支 test 发现之前的跟改没有 , 这样即可以找回 继续切换…

SE5 - BM1684 人工智能边缘开发板入门指南 -- 模型转换、交叉编译、yolov5、目标追踪

介绍 我们属于SoC模式&#xff0c;即我们在x86主机上基于tpu-nntc和libsophon完成模型的编译量化与程序的交叉编译&#xff0c;部署时将编译好的程序拷贝至SoC平台&#xff08;1684开发板/SE微服务器/SM模组&#xff09;中执行。 注&#xff1a;以下都是在Ubuntu20.04系统上操…

element-plus指定el-date-picker的弹出框位置

此处记录一下,通过popper-options指定popper出现的位置

Presto之Driver个数

一. 前言 在Presto的Stage Performace中&#xff0c;每个Operator中都会有Driver个数的显示&#xff0c;如下图所示。本文主要介绍Presto中是如何决定Driver的个数的。 二. Driver个数 在Presto中&#xff0c;一个pipeline中启动多少个Driver&#xff0c;是由此Pipeline处理的S…

tidb数据库5.4.3和6.5.3版本性能测试对比

作者&#xff1a; qizhining 原文来源&#xff1a; https://tidb.net/blog/5454621f 一、测试需求&#xff1a; 基于历史原因&#xff0c;我们的业务数据库一直使用5.4.3&#xff0c;最近由于研发提出需求&#xff1a;需要升级到6.5.3版本&#xff0c;基于版本不同&#x…

sql:SQL优化知识点记录(四)

&#xff08;1&#xff09;explain之ref介绍 type下的ref是非唯一性索引扫描具体的一个值 ref属性 例如&#xff1a;ti表先加载&#xff0c;const是常量 t1.other_column是个t1表常量 test.t1.ID&#xff1a;test库t1表的ID字段 t1表引用了shared库的t2表的col1字段&#x…

基于黑寡妇算法优化的BP神经网络(预测应用) - 附代码

基于黑寡妇算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码 文章目录 基于黑寡妇算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码1.数据介绍2.黑寡妇优化BP神经网络2.1 BP神经网络参数设置2.2 黑寡妇算法应用 4.测试结果&#xff1a;5.Matlab代…