Java多线程秘籍,掌握这5种方法,让你的代码优化升级

news2024/12/23 7:40:34

介绍5种多线程方法,助您提高编码效率!

如果您的应用程序与那些能够同时处理多个任务的应用程序相比表现不佳,很可能是因为它是单线程的。解决这个问题的方法之一是采用多线程技术。

d5fd3dc095c4d4feb08378fab66ed45f.jpeg

以下是一些可以考虑的方法:

  • 线程(Thread)
  • 并行流(Parallel Streams)
  • ExecutorService
  • ForkJoinPool
  • CompletableFuture

适当地使用这些方法,可以彻底改变您的应用程序,并推动您的职业发展。下面我们来看看如何将您的应用程序转变为高效的多线程应用。

1 线程(Thread)

第一种选择是使用线程(Thread)类。通过这种方式,您可以直接控制线程的创建和管理。以下是一个示例:

CustomTask 每隔50毫秒从0数到 count - 1。

768dab9dfe7fb894f572a8aac1457d4b.jpeg

a、b 和 c 是该类的三个实例。

Thread a =  new Thread( new CustomTask( "a",  5));
Thread b =  new Thread( new CustomTask( "b",  10));
Thread c =  new Thread( new CustomTask( "c",  5));

请注意,b 预计计数的次数是其他实例的两倍。您希望在 a 和 c 顺序运行的同时运行 b。

1abd3b6c492811c133f5240ab7994a47.jpeg

您可以非常容易地实现这种行为。

// 首先启动 a 和 b。
a.start();
b.start();

//  a 完成后开始 c。
a.join();
c.start();

以下是结果:

a- 0 from Thread- 0
b- 0 from Thread- 1
b- 1 from Thread- 1
a- 1 from Thread- 0
b- 2 from Thread- 1
a- 2 from Thread- 0
b- 3 from Thread- 1
a- 3 from Thread- 0
b- 4 from Thread- 1
a- 4 from Thread- 0
b- 5 from Thread- 1
c- 0 from Thread- 2
b- 6 from Thread- 1
c- 1 from Thread- 2
b- 7 from Thread- 1
c- 2 from Thread- 2
b- 8 from Thread- 1
c- 3 from Thread- 2
b- 9 from Thread- 1
c- 4 from Thread- 2

a 和 b 同时开始运行,轮流输出。a 完成后,c 开始执行。此外,它们全部在不同的线程中运行。通过手动创建 Thread 实例,您可以完全控制它们。

然而,请注意,低级线程处理也需要同步和资源管理,这可能更容易出错和复杂。

2 并行流(Parallel Streams)

当您需要对大型集合中的所有元素应用相同、重复且独立的任务时,并行流非常有效。

例如,图像调整大小是一个需要按顺序运行的繁重任务;当您有多个图像需要调整大小时,如果按顺序执行,将需要很长时间才能完成。在这种情况下,您可以使用并行流并行调整它们的大小,如下所示。

e9a88b21cee8324a878dbce087860a75.jpeg

这样,图像将同时调整大小,节省了大量宝贵的时间。

3 ExecutorService

当实现不需要精确的线程控制时,可以考虑使用 ExecutorService。ExecutorService 提供了更高层次的线程管理抽象,包括线程池、任务调度和资源管理。

ExecutorService 是一个接口,它最常见的用法是线程池。假设您有大量的异步任务堆积在一起,但是同时运行所有任务——每个任务占用一个线程——似乎太多了。线程池可以通过限制最大线程数来帮助您。

下面的示例中,我们使用 Executors.newFixedThreadPool() 实例化 ExecutorService 来使用 3 个线程运行 10 个任务。每个任务只打印一行。请注意,我们在之前的部分中重用了之前定义的 CustomTask。

ExecutorService executorService = Executors.newFixedThreadPool( 3);

for&nbsp;( int&nbsp;i&nbsp;=&nbsp; 0;&nbsp;i&nbsp;<&nbsp; 10;&nbsp;i++)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;executorService.submit( new&nbsp;CustomTask(String.valueOf(i),&nbsp; 1));
}

executorService.shutdown();

这将打印以下结果:

0- 0&nbsp;from&nbsp;pool- 1-thread- 1
2- 0&nbsp;from&nbsp;pool- 1-thread- 3
1- 0&nbsp;from&nbsp;pool- 1-thread- 2
4- 0&nbsp;from&nbsp;pool- 1-thread- 3
3- 0&nbsp;from&nbsp;pool- 1-thread- 2
5- 0&nbsp;from&nbsp;pool- 1-thread- 1
6- 0&nbsp;from&nbsp;pool- 1-thread- 1
7- 0&nbsp;from&nbsp;pool- 1-thread- 3
8- 0&nbsp;from&nbsp;pool- 1-thread- 2
9- 0&nbsp;from&nbsp;pool- 1-thread- 3

10 个任务在 3 个线程中运行。通过限制特定任务使用的线程数,您可以根据优先级分配线程数:对于重要且频繁的任务使用更多线程,对于琐碎或偶尔的任务使用较少线程。ExecutorService 具有高效和简洁的特点,是大多数多线程场景的首选选项。

如果您需要更多的控制和灵活性,请查看 ThreadPoolExecutor,它是 Executors.newFixedThreadPool() 返回的 ExecutorService 的实际实现。您可以直接创建其实例或将返回的 ExecutorService 实例转换为 ThreadPoolExecutor 实例以获得更多控制权。

4 ForkJoinPool

ForkJoinPool是另一种线程池,正如其名称所示。虽然它在许多其他异步方法的底层使用中,但对于可以分解为较小且独立子任务的任务来说,它也非常强大,这些任务可以通过分而治之的策略来解决。

其中一个任务是图像调整大小。图像调整大小是分而治之问题的一个很好的例子。使用ForkJoinPool,您可以将图像分成两个或四个较小的图像,并同时调整它们的大小。以下是ImageResizeAction的示例,它将图像调整为给定的大小。

5c7a467e9682f62e0fb0d29db62f88b6.jpeg

dd429937ba9cba2bbb339a45340dedb8.jpeg

请注意,ImageResizeAction继承了RecursiveAction。RecursiveAction用于定义递归的调整大小操作。在此示例中,图像被分成两半并并行调整大小。

您可以使用以下代码运行ImageResizeAction:

c1d347b76cb52a3c3f513e666ad5d7c5.jpeg

借助ForkJoinPool的帮助,您现在能够更高效地调整图像的大小,具有更好的可伸缩性,并最大程度地利用资源。

5 CompletableFuture

通过CompletableFuture,您可以完全发挥Future的功能,并拥有许多额外的特性。其中最突出的功能是它能够链式地连接异步操作,使您能够构建复杂的异步管道。

2acffdbfabed79817420257ea5552e73.jpeg

上述代码展示了CompletableFuture的一个关键方面:链式操作。通过CompletableFuture.supplyAsync(),首先创建并运行一个返回字符串结果的CompletableFuture。thenApply()接受前一个任务的结果,并执行其他操作,本例中是添加一个字符串。最后,thenAccept()打印生成的数据。结果如下所示:

ForkJoinPool.commonPool-worker- 1
ForkJoinPool.commonPool-worker- 1
ForkJoinPool.commonPool-worker- 1
Result:&nbsp;My&nbsp;name&nbsp;is&nbsp;Hyuni&nbsp;Kim

有3个任务没有在主线程中运行,这表明它们与主逻辑并行运行。当您有具有结果并需要链接的任务时,CompletableFuture将是一个很好的选择。

6 总结

多线程是一种强大的工具,可以帮助开发人员优化性能、提升用户体验、增强并发处理能力,并充分利用计算机的资源。


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

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

相关文章

Mac第三方恶意软件删除不了怎么办,这个方法你尝试了吗?

大多使用Mac电脑的用户&#xff0c;难免会遇到强制弹广告窗或者有些恶意软件在Mac电脑里删不掉的情况。是的&#xff0c;你的Mac可能已经感染了恶意软件。恶意软件除了传统的病毒、蠕虫和特洛伊木马之外&#xff0c;还有一个蓬勃发展的广告软件和间谍软件程序生态系统&#xff…

AT32固件库外设使用,ArduinoAPI接口移植,模块化

目录 一、ArduinoAPI移植一、通用定时器使用1.计时1.2.ETR外部时钟计数4.ArduinoAPI - timer 三、ADC1.ADC初始化&#xff08;非DMA&#xff09;2.ADC_DMA 规则通道扫描 六、USB HID IAP1.准备好Bootloader和app2.配置好时钟&#xff0c;一定要打开USB3.将生成的时钟配置复制到…

每日汇评:黄金形态确认牛市,再次尝试上行2000美元

金价挑战1988美元的关键阻力位&#xff0c;向2000美元进发&#xff1b; 在避险情绪中&#xff0c;美元随着美债收益率扩大复苏&#xff1b; 黄金价格在日线图上确认了一个多头标志&#xff0c;RSI指数仍然指向更多的上涨&#xff1b; 随着中东紧张局势再次引起人们的关注&#…

前列腺特异抗原(PSA)介绍

前列腺特异抗原(Prostate Specific Antigen&#xff0c;PSA)是由前列腺腺泡和导管的上皮细胞分泌的一种单链糖蛋白&#xff0c;在功能上属于类激肽释放酶的一种丝氨酸蛋白酶&#xff0c;参与精液的液化过程&#xff0c;是常规用于前列腺良性与恶性疾病诊断与鉴别诊断的重要指标…

LuaTable转C#的列表List和字典Dictionary

LuaTable转C#的列表List和字典Dictionaty 介绍lua中创建表测试lua中list表表转成List表转成Dictionary 键值对表表转成Dictionary 多类型键值对表表转成Dictionary 总结 介绍 之前基本都是从C#中的List或者Dictionary转成luaTable&#xff0c;很少会把LuaTable转成C#的List或者…

openEuler 22.03 LTS编译安装libreoffice并制作rpm包——筑梦之路

环境说明 操作系统&#xff1a;华为欧拉操作系统openEuler 22.03 lts x86_64 libreoffice版本&#xff1a;当前最新版本7.6 编译安装过程 1. 安装编译工具和依赖包 sudo yum install -y snappy snappy-devel autoconf automake libtool git gcc gcc-c gcc-objc make cmake…

超全整理,服务端性能测试-docker部署tomcat/redis(详细步骤)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、docker部署tom…

全电注塑机硬件选型

电机选型&#xff08;方法&#xff09; 在伺服电机选型计算当中其主要数据包括&#xff1a;负载/ 电机惯量比&#xff0c;加减速力矩&#xff0c; 负载转矩&#xff0c;连续过载时间等。选择原则是&#xff1a;首先根据转矩&#xff0d;速度特性曲线检查负载转矩&#xff0c;加…

解决photoshop中不能输入蒙文的方法(附所有软件、字体)

效果预览&#xff1a; ps版本&#xff1a;Adobe Photoshop 2020 windows版本&#xff1a;windows 11专业版 蒙文字体选用&#xff1a;Menk Garqag Tig 蒙文输入法&#xff1a;蒙科立智能输入发下载地址&#xff1a;蒙科立-蒙古文AI&#xff08;人工智能&#xff09;引领者 …

跨境电商测评方式有哪些?

对于做跨境电商平台的卖家来说&#xff0c;如果想要提高销量&#xff0c;测评是一个必不可少的环节&#xff0c;因为前期自然流量很难带来什么销售额&#xff0c;所以很多卖家选择进行测评来提升产品的排名、权重和销量&#xff0c;并增加订单量、点赞、店铺评价和产品评价等指…

Studio One6.5版本要不要更新?哪些人需要更新?更新了哪些内容

对于声卡调试Studio One6.5版本&#xff0c;是否需要更新&#xff1f;这是一个需要考虑的问题。各位好&#xff0c;我是coco玛奇朵。 关于Studio One6.5版本要不要更新&#xff1f;哪些人需要更新&#xff1f;更新了哪些内容&#xff1f;对于这些问题&#xff0c;今天我们来详…

Redis快速上手篇(二)(操作与数据类型)

Key 默认 16 个数据库&#xff0c;类似数组下标从 0 开始&#xff0c;初始默认使用 0 号库 config get databases 查询数据库总数量 dbsize 查看当前数据库的 key 的数量 flushdb 清空当前库 flushall 通杀全部库 keys * 获取当前库中的所有key select 0 选择第一个库 move ke…

VS2022 C# 读取 excel 2023年

今天是2023年6月26日&#xff0c;我有一个excel表要读数据&#xff0c;然后放到winform程序来处理&#xff0c;网上的资料太旧&#xff0c;很多用不起来&#xff0c;试了一个可以使用&#xff0c;记录一下&#xff1a; 一、excel文件后缀需要小写。 二、用VS2022建一个winform…

关于腾讯云轻量应用服务器性能测评,看这一篇文章就够了

腾讯云轻量应用服务器性能如何&#xff1f;为什么便宜是不是性能不行&#xff1f;腾讯云百科txybk.com从轻量应用服务器的CPU型号、处理器主频、内存、公网带宽、月流量和系统盘多方面来详细测评轻量性能&#xff0c;轻量应用服务器性价比高&#xff0c;并不是性能不行&#xf…

rk3588 SD 卡镜像扩容

先用一个卡复制镜像 Win32DiskImager 操作: https://blog.csdn.net/FL1623863129/article/details/118945754 复制之后镜像正常工作 但是仍旧只能显示32G 扩容 下载安装gparted https://blog.csdn.net/weixin_44589540/article/details/121580883 resize 拖过来就完了…

如何实现Android视音频数据对接到GB28181平台(SmartGBD)

为什么要开发Android平台GB28181&#xff1f; 在做Android平台GB28181接入模块之前&#xff0c;我们在RTMP推送播放、RTSP轻量级服务、转发、播放这块&#xff0c;已经有很多年的经验&#xff0c;这意味着&#xff0c;我们不需要重复造轮子&#xff0c;已有屏幕、摄像头或编码…

Keil uVision 5 MDK版软件安装包下载及安装教程(最详细图文教程)

目录 一.简介 二.安装步骤 软件&#xff1a;Keil uvision5版本&#xff1a;MDKv518语言&#xff1a;中文/英文大小&#xff1a;377.01M安装环境&#xff1a;Win11/Win10/Win8/Win7硬件要求&#xff1a;CPU2.59GHz 内存4G(或更高&#xff09;下载通道①百度网盘丨64位下载链接…

【Linux】第三站:Linux基本指令(二)

文章目录 一、通配符 *二、man指令三、cp指令1.先给一个文件里面写入数据2. cp指令拷贝普通文件3.cp指令拷贝文件目录4.常用的选项总结 四、mv指令1.mv命令简介2.使用 五、一些插曲1.一些注意事项2.指令的本质3.再谈输出重定向4.追加重定向5.输入重定向 六、cat指令七、more指令…

liunx Centos-7.5上 rabbitmq安装

在安装rabbitmq中需要注意&#xff1a; 1、rabbitmq依赖于erlang&#xff0c;需要先安装erlang 2、erlang和rabbitmq版本有对应关系 可参考网页&#xff1a;https://www.rabbitmq.com/which-erlang.html 第一步&#xff0c;安装编译工具及库文件,如果服务器上已经有了&…

大事务导致数据库恢复时间长

背景 客户的一套系统从凌晨开始出现运行缓慢&#xff0c;重启SQL Server服务后一个主要的数据库一直处在正在恢复的状态&#xff0c;多次重启SQL Server服务和服务器无果后请我们协助处理。 现象 在SSMS中看到数据库是正在恢复的状态&#xff0c;而且不能被访问。 分析 启动SQ…