【JavaEE】——多线程常用类

news2024/11/17 21:42:30

 8e19eee2be5648b78d93fbff2488137b.png

阿华代码,不是逆风,就是我疯

你们的点赞收藏是我前进最大的动力!!

希望本文内容能够帮助到你!!

目录

引入:

一:Callable和FutureTask类

1:对比Runnable

2:FutureTask类

3:代码示例

示例一:Runnable

​编辑示例二:Callable

二:ReentrantLock——可重入锁

1:与synchronized的区别

(1)不会阻塞

(2)公平锁

(3)唤醒机制不同

三:Semaphore——信号量

1:P操作

2:V操作

3:PV代码示例一

4:锁功能

四:CountDownLatch

1:引入

2:代码示例


引入:

通过之前的学习,我们了解到CAS本质上是JVM替我们封装好的,我们没有办法感知到

java.util.concurrent中存放了一些我们多线程编程时常用的类

看下面的一些接口:是不是非常熟悉,我们把这个packet包简称为(JUC)

e9ca2cbd045a46b1bbf59c50a57bf57b.png

一:Callable和FutureTask类

读法:“开了波哦”    译为:调用

1:对比Runnable

Runnable提供run方法返回值为void——关注过程,不关注执行结果

Callable提供call方法返回值类型就是执行结果的类型———更关注结果

2:FutureTask类

在Callable中的call方法中完成任务的描述后,我们要想办法把这个任务加载给线程Thread

但是Thread类中并没有给出Callable的构造方法,于是我们通过FutureTask这个中间类(可以理解为加载任务的装置),作为媒介,发射给Thread

即:

Callable中描述方法——卢本伟来啦~~

FutureTask中加载任务——卢本伟已准备就绪~~

Thread中传入futureTask任务执行——卢本伟启动!!

注:

Callable和FutureTask实例化的时候<>中要写返回结果的类型哦。

futureTask.get()方法是带有阻塞功能的,如果线程还没有执行完毕,get就会被阻塞,等到线程执行完了,return的结果就会被get返回回来

3:代码示例

老问题:计算前5000个数字之和
 

看以下两段代码——用Callable类写的代码比Runnable类写的代码更加优雅~~

示例一:Runnable

package thread;


public class ThreadDemon37 {
    private static int sum = 0;//全局变量用来保存最后的结果值
    public static void main(String[] args) throws InterruptedException {

        Thread t1 = new Thread(new Runnable() {
            int count = 0;//局部变量
            @Override
            public void run() {
                for (int i = 1 ; i <= 5000 ; i++){
                    count += i;
                }
                sum = count;
            }
        });
        t1.start();
        t1.join();
        System.out.println(sum);
    }


}

c187a3ca91944a6bab8894d443652fed.png示例二:Callable

此处我们不用再引入额外的成员变量了,直接借助返回值即可

package thread;

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


public class ThreadDemon38 {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        Callable<Integer> callable = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                int sum = 0;
                for (int i = 0; i <= 5000; i++) {
                    sum += i;
                }
                return sum;
            }
        };
        //Thread t1 = new Thread(callable);//Thread中没有提供构造函数来传入callable
        //引入FutureTask类,未来要完成的任务(任务还未执行)
        // 相当于在Callable中确定执行的任务
        //在FutureTask装置中完成任务加载——卢本伟准备就绪~~~
        //最后引入线程——卢本伟启动!!
        FutureTask<Integer> futureTask = new FutureTask<>(callable);
        Thread t1 = new Thread(futureTask);
        t1.start();
        t1.join();
        System.out.println(futureTask.get());//装置获得一下结果
    }
}

f9ffe1814187431eaf22c06ab0cba29c.png

补充一点:.futureTask.get()方法本身自带阻塞特性,如果Callable任务还没有执行完,是会一直等待它的返回值结果的

二:ReentrantLock——可重入锁

读音:“瑞安纯特老科” 翻译为:可重入锁

科普:ReentrantLock在很早以前是比没有发展起来的synchronized功能更加强大的,他提供了两个传统的方法lock和unlock,但是在写代码的过程中lock完后往往会忘记unlock解锁,所以一般把unlock操作放到finally里面使用

1:与synchronized的区别

(1)不会阻塞

我们知道synchronized加锁,如果线程“锁竞争”失败,会陷入阻塞等待,使用了ReentrantLodk提供了trylock方法后,如果加不上锁就会返回false,不会阻塞等待。

(2)公平锁

ReentrantLock中加锁依据是:公平锁,所有参与“加锁”的线程会被放进队列里面,按顺序进行加锁

(3)唤醒机制不同

synchronized提供wait和notify,ReentrantLock搭配Condition,功能比notify强一点

三:Semaphore——信号量

读音:“赛摸佛尔” 翻译为:信号量

科普:因为发明信号量的大佬迪杰斯特拉是个荷兰人,荷兰语的申请和释放首字母分别是P和V。实际上英语是acquire和release

1:P操作

申请一个可用资源,可用资源总数就会-1

2:V操作

释放一个可用资源,可用资源总数就会+1

打个比方:去停车场停车,现在有50个停车位,申请一个停车位(p操作),现有可用停车位为49;出来了一辆车(v操作),现有可用停车位为50;

3:PV代码示例一

package thread;

import java.util.concurrent.Semaphore;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: Hua YY
 * Date: 2024-09-30
 * Time: 10:26
 */
public class ThreadDemon39 {
    public static void main(String[] args) throws InterruptedException {
        Semaphore semaphore = new Semaphore(1);//资源数限制为1个
        semaphore.acquire();
        System.out.println("p操作");
        semaphore.acquire();//第二次申请
        System.out.println("p操作");
        semaphore.acquire();//第三次申请
        System.out.println("p操作");

    }
}

9cf9b627497042ea9426d8388842301a.png

4:锁功能

信号量是更为广义的锁

代码示例:继续沿用解决count计数器++线程安全问题的方式

package thread;

import java.util.concurrent.Semaphore;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: Hua YY
 * Date: 2024-09-30
 * Time: 10:33
 */
public class ThreadDemon40 {
    private static int count = 0;
    //引入Semaphore进行加锁
    private static Semaphore semaphore = new Semaphore(1);
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            try {
                semaphore.acquire();//加锁
                for (int i = 1 ; i <= 50000 ; i++){
                    count++;
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            semaphore.release();//解锁
        });
        Thread t2 = new Thread(() ->{
            try {
                semaphore.acquire();//加锁
                for (int i = 1 ; i <= 50000 ; i++){
                    count++;
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            semaphore.release();//解锁
        });

        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(count);
    }
}

4f2381686367498d83b6d9736d662e7c.png

四:CountDownLatch

1:引入

latch(锁存器)

举个例子,现在下载软件的速度非常快,用的是多线程下载方式,比如要下载一个1G大小的软件,我们把这个任务分成10份,分给10个线程同时进行下载,最后在拼在一起,速度就会快非常多。

这个“拼”的操作,就能被CountDownLatch感知到,比我们用join要更简单方便一些

2:代码示例

package thread;

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

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: Hua YY
 * Date: 2024-09-30
 * Time: 10:57
 */
public class ThreadDemon41 {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(10);//创建10个线程
        Random random = new Random();
        int time = (random.nextInt(4)+1)*1000;//time的范围[0,4]->[1,5]->[1000,5000]
        for(int i = 1 ; i <= 10 ; i++){
            int count = i;
            Thread t = new Thread(() ->{
                try {
                    Thread.sleep(random.nextInt(time));//产生的随机数的范围
                    System.out.println("第" + count + "线程的任务执行完毕");
                    latch.countDown();//告知CountDownLatch有一个任务已经执行完毕了
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            });
            t.start();
        }
        latch.await();//如果CountDownLatch中的任务还没有执行完毕,那么CountDownLatch就会陷入阻塞等待
        System.out.println("所有任务都已经执行完毕了");
    }
}

ab344df1b057467297751a6554e614ea.png

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

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

相关文章

多模态大模型 Qwen2-VL 下载、推理、微调实战案例来了

文章目录 技术交流Qwen2-VL 有什么新功能&#xff1f;模型结构模型效果模型下载模型推理模型微调 最近这一两周看到不少互联网公司都已经开始秋招发放Offer。 不同以往的是&#xff0c;当前职场环境已不再是那个双向奔赴时代了。求职者在变多&#xff0c;HC 在变少&#xff0c…

c#增删改查 (数据操作的基础)

//数据操作无非4种 //增删改查 是数据操作的基础 int[] ints { 110, 120, 119 }; //1. 查 在这里就是获取数组中的数据 int num ints[1]; //将数组中的某个元素取出来 Console.WriteLine(num); //2. 改 将数据从…

【C++并发入门】opencv摄像头帧率计算和多线程相机读取(下):完整代码实现

前言 高帧率摄像头往往应用在很多opencv项目中&#xff0c;今天就来通过简单计算摄像头帧率&#xff0c;抛出一个单线程读取摄像头会遇到的问题&#xff0c;同时提出一种解决方案&#xff0c;使用多线程对摄像头进行读取。上一期&#xff1a;【C并发入门】摄像头帧率计算和多线…

Elasticsearch使用Easy-Es + RestHighLevelClient实现深度分页跳页

注意&#xff01;&#xff01;&#xff01;博主只在测试环境试了一下&#xff0c;没有发到生产环境跑。因为代码还没写完客户说不用弄了( •̩̩̩̩&#xff3f;•̩̩̩̩ ) 也好&#xff0c;少个功能少点BUG 使用from size的时候发现存在max_result_window10000的限制&…

认知杂谈67《耐心!征服世界的秘籍》

内容摘要&#xff1a; 人生需家人朋友支持&#xff0c;自信源于解决问题的实力。别怕挫折&#xff0c;努力向前&#xff0c;反思自我。人生如游戏&#xff0c;靠自己打拼。学习要提升沟通、逻辑思维和时间管理等技能&#xff0c;读经典书籍&#xff0c;在平台学编程等&#xff…

ThreadLocal内存泄漏分析

一、ThreadLocal内存泄漏分析 1.1 ThreadLocal实现原理 1.1.1、set(T value)方法 查看ThreadLocal源码的 set(T value)方法&#xff0c;可以发现数据是存在了ThreadLocalMap的静态内部类Entry里面 其中key为使用弱引用的ThreadLocal实例&#xff0c;value为set传入的值。核…

C for Graphic:DNF手游残影效果

dnf手游在作死的道路上越行越远&#xff0c;困难罗特斯完全打不动&#xff0c;提前在抖音上细看攻略&#xff0c;基本能躲过机制不死&#xff0c;但是伤害不够&#xff0c;全时打满也还剩3000管血&#xff0c;组团半天炸团半天完全浪费一天。 个人觉得策划完全没必要这么逼…

Vite:为什么选 Vite

一、现实问题 在浏览器支持 ES 模块之前&#xff0c;JavaScript 并没有提供原生机制让开发者以模块化的方式进行开发。这也正是我们对 “打包” 这个概念熟悉的原因&#xff1a;使用工具抓取、处理并将我们的源码模块串联成可以在浏览器中运行的文件。 时过境迁&#xff0c;我…

开源模型应用落地-模型微调-语料采集-数据核验(三)

一、前言 在自然语言处理(NLP)的快速发展中,语料采集作为基础性的步骤显得尤为重要。它不仅为机器学习模型提供了所需的训练数据,还直接影响模型的性能和泛化能力。随着数据驱动技术的不断进步,如何有效并高效地收集、清洗和整理丰富多样的语料,已成为研究者和工程师们亟…

西门子智能从站

CPU1511作为CPU1513的智能IO设备_1511cpu-CSDN博客 掉站&#xff1a; 1511F作为智能从站其下挂的各子站设备掉站-通信与网络组件-找答案-西门子中国 同时做io控制器和智能从站&#xff1a; 1500PLC 同时做IO控制器和IO智能设备和DCS进行通讯-SIMATIC S7-1500系列-找答案-…

C++语言学习(3): type 的概念

type 的概念 C中的变量拥有类型&#xff0c; 这是显然的。 实际上&#xff0c;每个 object&#xff0c; 每个 reference&#xff0c; 每个 function&#xff0c; 每个 expression &#xff0c; 都有对应的 type &#xff08;类型&#xff09;&#xff1a; Each object, refer…

动手学LLM(ch2)——文本数据处理

前言 在这里&#xff0c;您将学习如何为训练大型语言模型&#xff08;LLMs&#xff09;准备输入文本。这包括将文本分割成单个词汇和子词汇token&#xff0c;然后将它们编码成向量表示&#xff0c;供大型语言模型&#xff08;LLM&#xff09;使用。您还将了解字节对编码等高级…

通信工程学习:什么是TFTP简单文件传输协议

TFTP&#xff1a;简单文件传输协议 TFTP&#xff08;Trivial File Transfer Protocol&#xff0c;简单文件传输协议&#xff09;是一种轻量级的文件传输协议&#xff0c;主要用于在计算机网络中传输小型文件。以下是对TFTP的详细解释&#xff1a; 一、TFTP简单文件传输协议的定…

无人机专业除理论外,飞手执照、组装、调试实操技术详解

无人机专业的学习除了丰富的理论知识外&#xff0c;飞手执照的获取、无人机的组装与调试等实操技术也是至关重要的。以下是对这些方面的详细解析&#xff1a; 一、无人机飞手执照 1. 必要性 法规要求&#xff1a;根据《民用无人驾驶航空器系统驾驶员管理暂行规定》等相关法规…

HTB:Oopsie[WriteUP]

目录 连接至HTB服务器并开启靶机 1.With what kind of tool can intercept web traffic? 2.What is the path to the directory on the webserver that returns a login page? 3.What can be modified in Firefox to get access to the upload page? 4.What is the acc…

关于TF-IDF的一个介绍

在这篇文章中我将介绍TF-IDF有关的一些知识&#xff0c;包括其概念、应用场景、局限性以及相应的代码。 一、概念 TF-IDF&#xff08;Term Frequency-Inverse Document Frequency&#xff09;是一种广泛用于信息检索和文本挖掘中的统计方法&#xff0c;用于评估一个词在一个文…

线路交换与分组交换的深度解析

1. 线路交换 原理 线路交换是一种在通信双方之间建立固定通信路径的方式。当用户发起通信时&#xff0c;网络为其分配一条专用的物理通道&#xff0c;这条通道在整个通话过程中保持不变。这意味着在通话期间&#xff0c;其他用户无法使用这条线路。 优点 稳定性&#xff1a…

在职场,没人告诉你的人情世故

职场中&#xff0c;想要过得游刃有余&#xff0c;就必须懂一些人情世故和处事原则。今天&#xff0c;给大家分享个人认为非常重要的5点人情世故&#xff0c;希望能帮你在职场里少吃点亏、多份从容。 01 不要空口道谢 在职场中&#xff0c;别人帮了你&#xff0c;口头道谢是基…

【GO语言】卡尔曼滤波例程

本文给出一个简单的卡尔曼滤波的 Go 语言实现示例&#xff0c;以及相应的讲解文档。 源代码 package mainimport ("fmt" )type KalmanFilter struct {x float64 // 状态估计P float64 // 估计误差协方差F float64 // 状态转移矩阵H float64 //…

在2核2G服务器安装部署MySQL数据库可以稳定运行吗?

阿里云2核2G服务器可以安装MySQL数据库吗&#xff1f;当然可以&#xff0c;并且可以稳定运行MySQL数据库&#xff0c;目前阿里云服务器网aliyunfuwuqi.com使用的就是阿里云2核2G服务器&#xff0c;在云服务器上安装MySQL数据库&#xff0c;可以稳定运行。 目前阿腾云用于运行M…