第四站:Java紫——多线程与并发的神秘之地(二)

深入线程池与Future/Promise异步编程

在Java并发编程的征途上,理解线程池的使用和掌握异步编程模型是不可或缺的一环。接下来,我们将深入探讨ExecutorService线程池的创建与使用,以及如何利用FutureCompletableFuture进行异步编程,进一步提升程序的性能与响应速度。

线程池:ExecutorService

线程池是一种预先创建好一定数量线程的机制,可以复用线程,减少线程创建销毁的开销,有效控制系统的并发规模。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolExample {public static void main(String[] args) {ExecutorService executor = Executors.newFixedThreadPool(3); // 创建固定大小线程池for (int i = 0; i < 5; i++) {Runnable worker = new WorkerThread("" + i);executor.execute(worker); // 提交任务到线程池}executor.shutdown(); // 关闭线程池,不再接受新任务while (!executor.isTerminated()) {// 等待所有任务完成}System.out.println("所有任务完成,线程池关闭。");}
}class WorkerThread implements Runnable {private final String command;WorkerThread(String s) {this.command = s;}@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + " 开始执行: " + command);processCommand();System.out.println(Thread.currentThread().getName() + " 结束执行: " + command);}private void processCommand() {try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}}
}
  • Executors类提供了多种线程池创建工厂方法,如newFixedThreadPool创建固定大小线程池。
  • execute(Runnable)用于提交不需要返回值的任务。
  • 正确关闭线程池,使用shutdown()isTerminated()确保所有任务完成。
Future与异步编程

Future代表异步计算的结果,提供了检查计算是否完成、获取计算结果以及取消计算的方法。

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;public class FutureExample {public static void main(String[] args) throws ExecutionException, InterruptedException {ExecutorService executor = Executors.newSingleThreadExecutor();Future<Integer> future = executor.submit(new Callable<Integer>() {@Overridepublic Integer call() throws Exception {Thread.sleep(2000);return 42; // 模拟耗时操作并返回结果}});System.out.println("Doing something else...");System.out.println("Result: " + future.get()); // 获取计算结果,会阻塞直到结果可用executor.shutdown();}
}
  • 使用submit(Callable)提交一个有返回值的任务,返回Future对象。
  • future.get()会阻塞直到结果可用,适用于同步等待结果的场景。
CompletableFuture:更强大的异步编程

CompletableFuture是Java 8引入的,它提供了丰富的链式调用API,支持非阻塞式的异步编程模型和更复杂的组合操作。

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class CompletableFutureExample {public static void main(String[] args) {ExecutorService executor = Executors.newFixedThreadPool(2);CompletableFuture.supplyAsync(() -> "Hello", executor).thenApplyAsync(s -> s + " World", executor).thenAcceptAsync(result -> System.out.println(result), executor).join(); // 非阻塞等待所有任务完成executor.shutdown();}
}
  • supplyAsync(Supplier<U>)异步供应结果。
  • thenApply(Function<? super T,? extends U>)接收上一步的计算结果,并应用函数产生新结果。
  • thenAccept(Consumer<? super T>)消费上一步的结果,无返回值。
  • join()等待异步结果完成,非阻塞版本的get()

通过上述示例,我们不仅学习了如何使用线程池来有效管理线程资源,还掌握了如何通过FutureCompletableFuture进行异步编程,以提升应用的响应性和并发处理能力。异步编程和线程池的结合,是现代Java应用提升性能和用户体验的关键技术之一。

深入线程池与Future/Promise异步编程:案例深化与高级应用

在进一步探讨线程池与异步编程的深度应用时,我们将通过更加复杂的案例来理解如何高效利用线程池处理批量任务,以及如何在实际场景中运用CompletableFuture进行异步处理和组合操作,实现高度灵活和高效的并发编程。

批量任务处理与线程池优化

想象一个场景,我们需要批量下载一系列图片,并在下载完成后对每张图片进行处理。这涉及到大量I/O密集型操作,非常适合使用线程池来提高效率。

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;public class BatchImageDownloader {private static final int THREAD_POOL_SIZE = 10;private static final ExecutorService executor = Executors.newFixedThreadPool(THREAD_POOL_SIZE);public static void downloadAndProcessImages(List<String> imageUrlList) {List<Future<Void>> futures = new ArrayList<>();for (String imageUrl : imageUrlList) {Future<Void> future = executor.submit(() -> {byte[] imageBytes = downloadImage(imageUrl);processImage(imageBytes);return null;});futures.add(future);}// 等待所有任务完成for (Future<Void> future : futures) {try {future.get();} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}}}private static byte[] downloadImage(String imageUrl) throws IOException {// 这里简略表示下载过程,实际应用中需要实现网络请求下载逻辑System.out.println("Downloading image from " + imageUrl);// 模拟下载操作Thread.sleep(1000);return new byte[0]; // 返回下载的图片字节数组}private static void processImage(byte[] imageBytes) {// 图片处理逻辑,这里简略表示System.out.println("Processing image...");}public static void main(String[] args) {List<String> urls = new ArrayList<>();urls.add("http://example.com/image1.jpg");urls.add("http://example.com/image2.jpg");// ... 添加更多图片URLdownloadAndProcessImages(urls);executor.shutdown();}
}
  • 通过批量提交下载任务至线程池,实现了并发下载和处理。
  • 使用Future列表来追踪所有任务的状态,确保所有任务完成后才继续执行后续逻辑。
  • 正确关闭线程池,确保资源释放。
CompletableFuture高级应用:组合异步操作

假设我们要实现一个服务,它需要先从数据库查询用户信息,然后基于用户ID从外部API获取更多数据,最后整合这些信息返回。这是一个典型的异步流程,非常适合使用CompletableFuture来实现。

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class CompletableFutureAdvanced {private static final ExecutorService executor = Executors.newFixedThreadPool(10);public static CompletableFuture<UserProfile> fetchUserProfile(String userId) {return CompletableFuture.supplyAsync(() -> {// 模拟从数据库获取用户基本信息User user = getUserFromDB(userId);return CompletableFuture.supplyAsync(() -> {// 模拟从外部API获取用户扩展信息UserProfile externalInfo = getExternalUserProfile(userId);return new UserProfile(user, externalInfo);}, executor);}).thenCompose(Function.identity());}// 模拟数据库查询方法private static User getUserFromDB(String userId) {System.out.println("Fetching user from DB: " + userId);return new User(userId, "John Doe"); // 返回模拟的用户对象}// 模拟外部API调用方法private static UserProfile getExternalUserProfile(String userId) {System.out.println("Fetching external info for: " + userId);return new UserProfile("Additional Info for " + userId); // 返回模拟的扩展信息}public static void main(String[] args) {String userId = "123";CompletableFuture<UserProfile> profileFuture = fetchUserProfile(userId);profileFuture.thenAccept(profile -> {System.out.println("User Profile Ready: " + profile);});executor.shutdown();}static class User {String id;String name;User(String id, String name) {this.id = id;this.name = name;}}static class UserProfile {User user;String additionalInfo;UserProfile(User user, String additionalInfo) {this.user = user;this.additionalInfo = additionalInfo;}@Overridepublic String toString() {return "UserProfile{" +"user=" + user +", additionalInfo='" + additionalInfo + '\'' +'}';}}
}
  • 使用thenCompose方法组合两个异步操作,先从数据库获取用户信息,然后基于结果异步获取外部信息,最后合并为一个UserProfile对象。
  • 这种链式调用和组合操作,展示了CompletableFuture的强大灵活性和非阻塞处理能力。

通过以上案例,我们深入体会到了线程池在处理批量任务时的效率优势,以及CompletableFuture在异步编程中的强大功能,它们是解决复杂并发问题的利器。在实际应用中,合理设计和使用这些工具,能够显著提升应用的性能和响应速度。

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

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

相关文章

SRAM和DRAM

1.SRAM&#xff08;静态RAM&#xff09; 把存放一个二进制位的物理器件称为存储元&#xff0c;它是存储器最基本的构件。 地址码相同的多个存储元构成一个存储单元。 存储单元的集合构成存储体。 静态RAM的存储元是用双稳态触发器&#xff08;六晶体管MOS&#xff09;来记忆…

介绍autofit

autofit.js是一个可以让你的PC项目自适应屏幕的工具&#xff0c;其原理非常简单&#xff0c;即在scale等比缩放的基础上&#xff0c;向右或向下增加了宽度或高度&#xff0c;以达到充满全屏的效果&#xff0c;使用autofit.js不会挤压、拉伸元素&#xff0c;它只是单纯的设置了容…

每天一个项目管理概念之虚拟团队

项目管理中的虚拟团队是一个由分布在全球各地的成员组成的团体&#xff0c;他们利用现代通信技术和网络工具进行协作&#xff0c;以实现共同的项目目标。虚拟团队打破了传统的物理办公室界限&#xff0c;允许来自不同文化背景、时区和专业领域的个人协同工作。这一概念在21世纪…

vue3 数据逻辑处理 将同一个 对应的id 的区分出来

先上代码 const groupedOptions {} // 使用对象来存储分组结果data.list.forEach(item > { // 遍历 groupList.value&#xff0c;检查是否有匹配的 idgroupList.value.forEach(group > {if (group.id item.groupId) {// 如果 group.id 在 groupedOptions 中不存在&…

C#结合JS 修改解决 KindEditor 弹出层问题

目录 问题现象 原因分析 范例运行环境 解决问题 修改 kindeditor.js C# 服务端更新 小结 问题现象 KindEditor 是一款出色的富文本HTML在线编辑器&#xff0c;关于编辑器的详细介绍可参考我的文章《C# 将 TextBox 绑定为 KindEditor 富文本》&#xff0c;这里我们讲述在…

人工智能不是一根魔杖——它有内在的问题

人工智能不是一根魔杖——它有内在的问题&#xff0c;很难解决&#xff0c;而且可能很危险 到目前为止&#xff0c;我们都听说过很多关于人工智能(AI)的事情。你可能已经使用过无数可用的人工智能工具。对一些人来说&#xff0c;人工智能就像一根预测未来的魔杖。 但人工智能…

[原创][Delphi多线程]使用TMonitor, TEvent和TQueue配合实现TThreadQueue的经典使用案例.

[简介] 常用网名: 猪头三 出生日期: 1981.XX.XX QQ: 643439947 个人网站: 80x86汇编小站 https://www.x86asm.org 编程生涯: 2001年~至今[共22年] 职业生涯: 20年 开发语言: C/C、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python 开发工具: Visual Studio、Delph…

1 小时快速入门 DolphinDB

自从 DolphinDB 技能认证上线以来&#xff0c;大家学习和报考的热情就一路高涨。为了响应这份热情&#xff0c;DolphinDB 推出了一系列在线免费培训课程视频来帮助大家系统地学习和掌握 DolphinDB。 经过前后数月的精心准备和科学编排&#xff0c;《 DolphinDB 数据库入门》系…

Eureka Client 配置与高级功能

在上一篇文章中&#xff0c;我们介绍了 Eureka 的基本概念以及如何配置 Eureka Server。在这篇文章中&#xff0c;我们将继续介绍 Eureka Client 的配置以及 Eureka 的一些高级功能。 一、Eureka Client 配置 在一个微服务项目中&#xff0c;需要配置 Eureka Client 以便向 E…

有没有和ai聊天的软件?介绍这三款聊天软件

有没有和ai聊天的软件&#xff1f;在科技飞速发展的今天&#xff0c;人工智能&#xff08;AI&#xff09;已经渗透到我们生活的方方面面&#xff0c;其中AI聊天软件以其独特的魅力&#xff0c;赢得了越来越多用户的青睐。今天&#xff0c;我们就来一起探索三款智能聊天软件的功…

LogicFlow 学习笔记——9. LogicFlow 进阶 节点

LogicFlow 进阶 节点&#xff08;Node&#xff09; 连线规则 在某些时候&#xff0c;我们可能需要控制边的连接方式&#xff0c;比如开始节点不能被其他节点连接、结束节点不能连接其他节点、用户节点后面必须是判断节点等&#xff0c;想要达到这种效果&#xff0c;我们需要为…

Typora—适用于 Mac 和 Win 系统的优秀 Markdown 文本编辑器

Typora 是一款适用于 Mac 和 Win 系统的优秀 Markdown 文本编辑器&#xff0c;它以其简洁易用的界面和强大的功能受到了众多用户的喜爱。 首先&#xff0c;Typora 的界面设计非常简洁直观&#xff0c;没有过多繁杂的菜单和按钮&#xff0c;让用户能够专注于写作本身。它采用实时…

Java高级编程技术详解:从多线程到算法优化的全面指南

复杂度与优化 复杂度与优化在算法中的应用 算法复杂度是衡量算法效率的重要指标。了解和优化算法复杂度对提升程序性能非常关键。本文将介绍时间复杂度和空间复杂度的基本概念&#xff0c;并探讨一些优化技术。 时间复杂度和空间复杂度 时间复杂度表示算法执行所需时间随输…

LVS – NAT 模式集群构建

目录 1 环境准备 1.1 准备四台服务器 1.2 IP与网关均按照下图配置 1.3 网卡配置 1.4 real server 安装 web服务 1.5 安装ipvsadm 管理工具 2 使用ipvsadm管理LVS 2.1 创建集群指定使用的算法 2.2 添加真实服务器指定工作原理 2.3 查看是否正确创建集群 2.4 开启FORWARD路由转发…

每日一练 - PIM协议报文类型辨析

01 真题题目 在 PIM 协议中可能存在的报文是&#xff1a; A. JOIN/PRUNE B. ASSERT C. BOOTSTRAP D. REGISTER 02 真题答案 AB 03 答案解析 PIM&#xff08;Protocol Independent Multicast&#xff09;协议有两个主要的操作模式&#xff1a;PIM-Dense Mode (PIM-DM) 和 PIM…

​一个高清影像下载插件

数据是GIS的血液&#xff01; 虽然我们在水经微图&#xff08;简称“微图”&#xff09;中可以下载各种各样丰富的地图数据&#xff0c;但相信大家对数据的追求是无止境的。 我们现在就来分享一下&#xff0c;如何在QGIS中下载高清卫星影像的方法。 如果你需要最新版本的QGI…

最新下载:Hype 4 mac版【软件附加安装教程】

Hype是一款强大的Mac OS平台 HTML5 创作工具&#xff0c;它可以在网页上做出赏心悦目的动画效果&#xff0c;创建丰富的网页交互动画&#xff0c;支持层、时间轴等编辑方式&#xff0c;并能很好的导出HTML5/CSS3/JavaScript&#xff0c;在台式机&#xff0c;智能手机和iPad上流…

一、sorted()函数的使用

numbers[2,23,1,3,434,23,23] demosorted(numbers)#正常升序 print("\n") print(demo) demo1sorted(numbers,reverseTrue)#加上reverse变为降序 demo2sorted(numbers,reverseFalse)#加上reverse变为降序 print(demo1) print(demo2)#reverse默认为False names[Addf,aD…

裁剪图片的最简单方法?这四种裁剪方法真的超级简单!

裁剪图片的最简单方法&#xff1f;在丰富多彩的现代生活中&#xff0c;图片成为了我们表达、沟通甚至展示身份的重要媒介&#xff0c;然而&#xff0c;无论是出于个人审美还是专业需求&#xff0c;图片的格式和尺寸往往成为了我们不得不面对的问题&#xff0c;特别是那些未经雕…

flink1.12.0学习笔记(一)-部署与入门

flink1.12.0学习笔记&#xff08;1&#xff09;-部署与入门 1-1-Flink概述 Flink诞生 Flink 诞生于欧洲的一个大数据研究项目 StratoSphere。该项目是柏林工业大学的一个研究性项目。早期&#xff0c; Flink 是做 Batch 计算的&#xff0c;但在 2014 年&#xff0c; StratoS…