探索并发编程

引言

在现代软件开发中,尤其是面对高性能、高并发需求的应用场景,Java的并发编程能力显得尤为重要。Java提供了丰富的API和框架来支持开发者构建高效、可靠的多线程应用程序。本文将深入探讨Java并发编程的核心概念,重点讲解线程池的使用、Future与Callable接口的高级应用,以及如何通过这些工具提升程序的执行效率和响应性。

 线程池:资源管理的艺术

线程池是Java并发编程中的一个核心组件,它通过复用线程来减少线程创建和销毁的开销,有效控制系统资源。`ExecutorService`接口及其实现类,如`ThreadPoolExecutor`,为管理线程池提供了灵活的机制。

创建线程池:

```java

ExecutorService executor = Executors.newFixedThreadPool(10);


```

上述代码创建了一个固定大小的线程池,池中维持10个线程。根据不同的应用场景,还可以选择`newCachedThreadPool`(灵活扩容缩容)或`newSingleThreadExecutor`(单一工作线程)等策略。

任务提交与执行:

```java

executor.submit(() -> {// 任务逻辑
});


```

使用`submit`方法可以提交一个实现了`Runnable`接口的任务。对于需要获取结果的任务,应使用`Callable`接口结合`Future`。

 Future与Callable:异步编程的利器

与`Runnable`接口只能执行无返回值的任务不同,`Callable`接口允许任务有返回值,并且可以抛出异常。配合`Future`接口,可以在任务完成后检索结果或捕获异常,非常适合处理耗时操作而不阻塞主线程的场景。

```java

Future<String> future = executor.submit(() -> {Thread.sleep(1000); // 模拟耗时操作return "Task Result";
});try {System.out.println("Result: " + future.get()); // 获取结果,此方法会阻塞直到结果可用
} catch (InterruptedException | ExecutionException e) {e.printStackTrace();
}


```

 异步编程的最佳实践

1. 避免Future.get()的直接阻塞: 使用`get(long timeout, TimeUnit unit)`设定超时时间,或者采用CompletionService来更优雅地处理完成的任务。

2. 资源清理: 使用完毕后,记得关闭线程池以释放资源。
   
   ```java
 

  executor.shutdown();


   ```

3. 异常处理: 在任务执行过程中妥善处理异常,确保不会因为某个任务失败而影响整个线程池的正常运行。

4. 监控与调试: 利用线程池提供的统计信息进行性能监控,如`ThreadPoolExecutor`的`getQueue()`、`getCompletedTaskCount()`等方法。

当然,接下来我将通过三个具体案例进一步阐述Java并发编程中线程池、Future与Callable的实战应用。

### for example 1:使用线程池执行批量任务

这个案例展示如何使用线程池执行一批独立的任务,并在所有任务完成后执行后续操作。```java

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolExample {public static void main(String[] args) {ExecutorService executor = Executors.newFixedThreadPool(5); // 创建固定大小线程池for (int i = 0; i < 10; i++) {final int taskId = i;executor.submit(() -> {System.out.println("Executing Task " + taskId + " by " + Thread.currentThread().getName());try {Thread.sleep(1000); // 模拟任务执行时间} catch (InterruptedException e) {e.printStackTrace();}});}executor.shutdown(); // 关闭线程池,不再接受新任务while (!executor.isTerminated()) {// 等待所有任务完成}System.out.println("All tasks completed");}
}


```

### for example 2:利用Future获取异步计算结果

本案例演示如何提交Callable任务至线程池并获取其结果,展示了Future的使用方式。```java

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;public class FutureCallableExample {public static void main(String[] args) throws InterruptedException, ExecutionException {ExecutorService executor = Executors.newFixedThreadPool(3);List<Future<Integer>> results = new ArrayList<>();for (int i = 0; i < 3; i++) {Callable<Integer> task = () -> {Thread.sleep(1000); // 模拟计算return i * i;};Future<Integer> future = executor.submit(task);results.add(future);}for (Future<Integer> future : results) {System.out.println("Result: " + future.get()); // 获取并打印结果}executor.shutdown();}
}


```

### for example 3:使用CompletionService优化任务处理

CompletionService结合了ExecutorService和BlockingQueue的优点,它允许我们按照完成的顺序处理任务的结果,而不是提交的顺序。```java
import java.util.concurrent.*;public class CompletionServiceExample {public static void main(String[] args) throws InterruptedException, ExecutionException {ExecutorService executor = Executors.newFixedThreadPool(3);CompletionService<Integer> completionService = new ExecutorCompletionService<>(executor);for (int i = 0; i < 3; i++) {final int taskId = i;completionService.submit(() -> {Thread.sleep((long) (Math.random() * 800)); // 模拟不同长度的任务执行时间return taskId * taskId;});}for (int i = 0; i < 3; i++) {Future<Integer> result = completionService.take(); // 阻塞等待下一个完成的任务System.out.println("Task result: " + result.get());}executor.shutdown();}
}


```

以上三个案例分别展示了线程池的基本使用、通过Future获取异步计算结果,以及如何使用CompletionService来优化异步任务的处理流程。这些技巧在实际开发中能显著提升应用的并发处理能力和响应速度。

### for example 4:实现带超时控制的Future任务

有时候,我们希望对任务执行设置超时限制,以防止因个别任务长时间未完成而导致整个系统挂起。以下是如何使用Future的`get(long timeout, TimeUnit unit)`方法来实现这一需求。```java

import java.util.concurrent.*;public class FutureTimeoutExample {public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {ExecutorService executor = Executors.newSingleThreadExecutor();Future<String> future = executor.submit(() -> {Thread.sleep(5000); // 模拟耗时操作return "Task done!";});try {System.out.println("Task result: " + future.get(3, TimeUnit.SECONDS)); // 设置3秒超时} catch (TimeoutException e) {future.cancel(true); // 超时则取消任务System.out.println("Task timed out!");}executor.shutdownNow(); // 关闭线程池}
}


```

### for example 5:线程池的动态调整策略

本案例演示如何根据系统负载动态调整线程池的大小,这里使用`ThreadPoolExecutor`自定义创建,利用其构造函数中的参数实现动态调整。```java

import java.util.concurrent.*;public class DynamicThreadPoolExample {public static void main(String[] args) {ThreadPoolExecutor executor = new ThreadPoolExecutor(1, // 核心线程数6, // 最大线程数1, // 空闲线程存活时间TimeUnit.SECONDS, // 时间单位new ArrayBlockingQueue<>(3), // 工作队列new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略,直接在调用者线程执行);for (int i = 0; i < 10; i++) {final int taskId = i;executor.execute(() -> {System.out.println("Executing Task " + taskId + " by " + Thread.currentThread().getName());try {Thread.sleep(1000); // 模拟任务执行} catch (InterruptedException e) {Thread.currentThread().interrupt();}});}executor.shutdown();}
}


```

### for example 6:Callable与Future用于并发数据处理

这个案例通过并行处理数据集合,展示了Callable与Future在数据密集型任务中的应用,利用多线程加速数据处理过程。```java

import java.util.*;
import java.util.concurrent.*;public class DataProcessingExample {public static void main(String[] args) throws ExecutionException, InterruptedException {ExecutorService executor = Executors.newFixedThreadPool(4);List<Integer> data = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);List<Future<Integer>> futures = new ArrayList<>();for (Integer number : data) {final int num = number;Future<Integer> future = executor.submit(() -> processNumber(num));futures.add(future);}List<Integer> processedData = new ArrayList<>();for (Future<Integer> future : futures) {processedData.add(future.get()); // 获取并收集处理后的结果}System.out.println("Processed Data: " + processedData);executor.shutdown();}private static Integer processNumber(Integer number) {try {Thread.sleep(500); // 模拟耗时处理} catch (InterruptedException e) {Thread.currentThread().interrupt();}return number * number;}
}


```

以上三个额外案例进一步展示了Java并发编程中的一些进阶技巧,包括任务超时处理、线程池动态调整策略,以及如何在数据处理中高效利用Callable与Future。这些技术点在构建高性能、响应迅速的系统时尤为关键。

 结论

Java并发编程是构建高性能服务不可或缺的一部分。通过合理利用线程池、Future与Callable,开发者不仅能提升程序的执行效率,还能增强系统的稳定性和可维护性。掌握这些高级特性,对于应对复杂多变的并发场景至关重要。未来,随着Java生态的不断进化,更多高级并发工具和模式的出现将进一步简化并发编程,提升开发效率和应用性能。

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

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

相关文章

OpenAI、微软、智谱AI 等全球 16 家公司共同签署前沿人工智能安全承诺

人工智能&#xff08;AI&#xff09;的安全问题&#xff0c;正以前所未有的关注度在全球范围内被讨论。 日前&#xff0c;OpenAI 联合创始人、首席科学家 Ilya Sutskever 与 OpenAI 超级对齐团队共同领导人 Jan Leike 相继离开 OpenAI&#xff0c;Leike 甚至在 X 发布了一系列…

webpack5零基础入门-15样式兼容性问题处理

1.下载相关依赖 npm i postcss-loader postcss postcss-preset-env -D 2.在webpack.config.js中配置 注意&#xff1a;postcss-loader要在css-loader后面配置 3.写一个flex布局&#xff0c;flex是存在一定的兼容性问题的 4.打包 可以看到打包后未被处理 1.下载相关依赖 np…

MySQL 查询某个字段含有字母数字的值

在数据库管理中&#xff0c;常常需要查询某个字段包含特定类型数据的记录。本文将详细介绍如何在 MySQL 中查询某个字段含有字母和数字的值&#xff0c;并提供至少五个具体示例&#xff0c;帮助您更好地理解和应用这些查询方法。 1. 概述 在 MySQL 中&#xff0c;使用正则表达…

YOLOv8绘制map曲线图

yolov8源码绘制的map曲线图不够清晰&#xff0c;python代码绘制的曲线图导入word之后清晰度也不够高&#xff0c;所以选择使用matlab来绘制曲线图&#xff0c;matlab可以直接复制图窗到word中&#xff0c;在转换成pdf也不会失真。点击编辑&#xff0c;复制图窗即可复制到word中…

MySQL + JPA 动态条件查询

maven 依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId><version>2.3.12.RELEASE</version> </dependency>实体类 package cn.xxx.xxx.project.dal.my…

Aspect打印接口请求信息和返回内容

文章目录 引言I 打印请求信息II 方法参数反序列化异常解决方案1解决方案2引言 2024-05-18 13:43:19.358 [http-nio-5050-exec-1] [58497D6655] INFO - 请求url : http://192.168.20.xx:xxx/userAdmin/login 2024-05-18 13:43:19.358 [http-nio-5050-exec-1]

C - Sigma Problem(AtCoder Beginner Contest 353)

题目的链接: C - Sigma Problem (atcoder.jp) 题目&#xff1a; 样例&#xff1a; 题目大致含意: 给你n个数&#xff0c;让你对这n个数进行操作&#xff0c;比如当前是第i个&#xff0c;那么让a[i] 和 后面的每个数进行相加, 例如a[i] a[i 1] 注意的是a[i] a[i 1]的结果…

linux的用户管理

新建用户&#xff1a;1.useradd 2.passwd 完成的操作&#xff1a; (1)/etc/passwd添加一行 (2)/etc/shadow添加一行 (3)/etc/group添加一行 (4)创建用户家目录 (5)创建用户邮件文件 例&#xff1a;创建用户jerry&#xff0c;要求: uid:777&am…

20240522每日后端---------如何回答面试官的问题

问题 通常面试官会抛出一个问题&#xff0c;比如redis的雪崩&#xff0c;mysql的索引&#xff0c;spring的bean生命周期等等。 一般我们面试时候&#xff0c;当听到面试官问问题&#xff0c;下意识的就会在脑海中搜索答案&#xff0c;但是实际上这是不正确的做法&#xff0c;我…

【git】开发提交规范(feat、fix、perf)

这段时间收到的需求很多&#xff0c;可能是临近两周一次的大版本灰度上线&#xff0c;这次产生了一个关于git的思考&#xff0c;就是各个版本之间怎么管理的问题&#xff0c;这里做出我自己的一些方法。 首先&#xff0c;既然已经明确了remote分支中的release分支为主分支&…

多线程讲解(详解)

目录 什么是多线程&#xff1f; 为什么要使用多线程&#xff1f; 线程的创建 使用Thread实现 从以上代码我们梳理一下多线程创建步骤&#xff1a; 注意&#xff1a; 小示例 首先&#xff0c;引入依赖 然后&#xff0c;按照我们刚刚说的构建多线程的步骤进行构建&#…

Arthas,应用诊断利器!【送源码】

Arthas 是一款线上监控诊断产品&#xff0c;通过全局视角实时查看应用 load、内存、gc、线程的状态信息&#xff0c;并能在不修改应用代码的情况下&#xff0c;对业务问题进行诊断&#xff0c;包括查看方法调用的出入参、异常&#xff0c;监测方法执行耗时&#xff0c;类加载信…

Model-Based Pose Estimation for Rigid Objects(基于SIFT)

6D目标检测工程落地需求的小算力算法&#xff0c;本文具有借鉴意义&#xff0c;但对于特征点少的目标不太好用。 摘要 在多个实际应用中&#xff0c;经常会遇到确定图像中出现的物体姿态的问题。处理这一挑战的最有效策略是按照基于模型的范式进行&#xff0c;这涉及构建物体…

Qt快速入门到熟练(电子相册项目(一))

经过一段时间的学习&#xff0c;相信大家对QT的基本用法都有所了解&#xff0c;从这篇文章开始&#xff0c;我准备记录一下电子相册的项目的一个学习过程。 实现项目创建功能 对于这个电子相册的项目&#xff0c;我并没有在一开始就把所有可能用到的功能模块去事无巨细的考虑周…

通过域名接口申请免费的ssl多域名证书

来此加密已顺利接入阿里云的域名接口&#xff0c;用户只需一键调用&#xff0c;便可轻松完成域名验证&#xff0c;从而更高效地申请证书。接下来&#xff0c;让我们详细解读一下整个操作过程。 来此加密官网 免费申请SSL证书 免费SSL多域名证书&#xff0c;泛域名证书。 首先&a…

Intellij IDEA创建springboot项目

1、点击 Create New Project 2、选择 Spring Initializr —> 点击下一步 3、备注&#xff1a; Artifact为项目名称 group为项目组名 language设置为java packaging为打包方式 3、选择相应的依赖&#xff0c;也可以自己导入&#xff0c;在Developer Tools 、Web 、SQL 中选…

开箱即用,简单上手体验LobeChat搭建私人ChatGPT

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

【LeetCode算法】第69题:x的平方根

目录 一、题目描述 二、初次解答 三、官方解法 四、总结 一、题目描述 二、初次解答 1. 思路&#xff1a;第一次想到的是让i从1开始遍历&#xff0c;看i*ix是否成立&#xff0c;但是这样就会导致i*i超出了int的范围&#xff0c;无法正常求解。第二次&#xff0c;想着比较x/…

H800基础能力测试

H800基础能力测试 参考链接A100、A800、H100、H800差异H100详细规格H100 TensorCore FP16 理论算力计算公式锁频安装依赖pytorch FP16算力测试cublas FP16算力测试运行cuda-samples 本文记录了H800基础测试步骤及测试结果 参考链接 NVIDIA H100 Tensor Core GPU Architecture…

2024.5.23 作业 xyt

今日课堂内容&#xff1a;超时检测 数据库 select函数 #include <myhead.h> int main(int argc, const char *argv[]) {//1、定义检测容器fd_set readfds;//2、清空内容FD_ZERO(&readfds);//3、将文件描述符放入集合中FD_SET(0, &readfds);//4、定义超时时间变…