深入浅出获取线程的不同方式

在上一篇博客中,我们提到了创建线程的 3 种方式,一种是直接继承 Thread,一种是实现 Runnable 接口,另外一种是实现 Callable 接口。
前 2 种方式都有一个缺陷:在执行完任务之后无法获取执行结果。
如果需要获取执行结果,就必须通过共享变量或者线程通信的方式来达到目的,这样使用起来就比较麻烦。
Java 1.5 提供了 Callable、Future、FutureTask,它们可以在任务执行完后得到执行结果,今天我们就来详细的了解一下。

无返回值的 Runnable

由于Runnablerun()方法的返回值为 void:
public interface Runnable { public abstract void run(); }
所以在执行完任务之后无法返回任何结果。

有返回值的 Callable

Callable 位于java.util.concurrent包下,也是一个接口,它定义了一个call()方法:
public interface Callable<V> { V call() throws Exception; }
可以看到,call()方法返回的类型是一个 V 类型的泛型。
那怎么使用 Callable 呢?
一般会配合 ExecutorService来使用。
ExecutorService 是一个接口,位于java.util.concurrent包下,它是 Java 线程池框架的核心接口,用来异步执行任务。它提供了一些关键方法用来进行线程管理。
下面的例子就用到了 ExecutorService 的 submit 方法。
// 创建一个包含5个线程的线程池 ExecutorService executorService = Executors.newFixedThreadPool(5); // 创建一个Callable任务 Callable<String> task = new Callable<String>() { public String call() { return "Hello from " + Thread.currentThread().getName(); } }; // 提交任务到ExecutorService执行,并获取Future对象 Future[] futures = new Future[10]; for (int i = 0; i < 10; i++) { futures[i] = executorService.submit(task); } // 通过Future对象获取任务的结果 for (int i = 0; i < 10; i++) { System.out.println(futures[i].get()); } // 关闭ExecutorService,不再接受新的任务,等待所有已提交的任务完成 executorService.shutdown();
我们通过 Executors 工具类来创建一个 ExecutorService,然后向里面提交 Callable 任务,然后通过 Future 来获取执行结果。
为了做对比,我们再来看一下使用 Runnable 的方式:
// 创建一个包含5个线程的线程池 ExecutorService executorService = Executors.newFixedThreadPool(5); // 创建一个Runnable任务 Runnable task = new Runnable() { public void run() { System.out.println("Hello from " + Thread.currentThread().getName()); } }; // 提交任务到ExecutorService执行 for (int i = 0; i < 10; i++) { executorService.submit(task); } // 关闭ExecutorService,不再接受新的任务,等待所有已提交的任务完成 executorService.shutdown();
可以看到,使用 Runnable 的方式要比 Callable 的方式简单一些,但是 Callable 的方式可以获取执行结果,这是 Runnable 做不到的。

异步计算结果 Future 接口

在前面的例子中,我们通过 Future 来获取 Callable 任务的执行结果,那么 Future 是什么呢?
Future 位于java.util.concurrent包下,它是一个接口:
public interface Future<V> { boolean cancel(boolean mayInterruptIfRunning); boolean isCancelled(); boolean isDone(); V get() throws InterruptedException, ExecutionException; V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; }
一共声明了 5 个方法:
  • cancel()方法用来取消任务,如果取消任务成功则返回 true,如果取消任务失败则返回 false。参数 mayInterruptIfRunning 表示是否允许取消正在执行却没有执行完毕的任务,如果设置 true,则表示可以取消正在执行过程中的任务。如果任务已经完成,则无论 mayInterruptIfRunning 为 true 还是 false,此方法肯定返回 false,即如果取消已经完成的任务会返回 false;如果任务正在执行,若 mayInterruptIfRunning 设置为 true,则返回 true,若 mayInterruptIfRunning 设置为 false,则返回 false;如果任务还没有执行,则无论 mayInterruptIfRunning 为 true 还是 false,肯定返回 true。
  • isCancelled()方法表示任务是否被取消成功,如果在任务正常完成前被取消成功,则返回 true。
  • isDone()方法表示任务是否已经完成,若任务完成,则返回 true;
  • get()方法用来获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回;
  • get(long timeout, TimeUnit unit)用来获取执行结果,如果在指定时间内,还没获取到结果,就直接返回 null。
也就是说 Future 提供了三种功能:
  • 1)判断任务是否完成;
  • 2)能够中断任务;
  • 3)能够获取任务执行结果。
由于 Future 只是一个接口,如果直接 new 的话,编译器是会有一个警告的,它会提醒我们最好使用 FutureTask。
实际上,FutureTask 是 Future 接口的一个唯一实现类,我们在前面的例子中executorService.submit()返回的就是 FutureTask。

异步计算结果 FutureTask 实现类

我们来看一下 FutureTask 的实现:
public class FutureTask<V> implements RunnableFuture<V>
FutureTask 类实现了 RunnableFuture 接口,我们看一下 RunnableFuture 接口的实现:
public interface RunnableFuture<V> extends Runnable, Future<V> { void run(); }
可以看出 RunnableFuture 继承了 Runnable 接口和 Future 接口,而 FutureTask 实现了 RunnableFuture 接口。所以它既可以作为 Runnable 被线程执行,又可以作为 Future 得到 Callable 的返回值。
FutureTask 提供了 2 个构造器:
public FutureTask(Callable<V> callable) { } public FutureTask(Runnable runnable, V result) { }
当需要异步执行一个计算并在稍后的某个时间点获取其结果时,就可以使用 FutureTask。举个🌰
// 创建一个固定大小的线程池 ExecutorService executorService = Executors.newFixedThreadPool(3); // 创建一系列 Callable Callable<Integer>[] tasks = new Callable[5]; for (int i = 0; i < tasks.length; i++) { final int index = i; tasks[i] = new Callable<Integer>() { @Override public Integer call() throws Exception { TimeUnit.SECONDS.sleep(index + 1); return (index + 1) * 100; } }; } // 将 Callable 包装为 FutureTask,并提交到线程池 FutureTask<Integer>[] futureTasks = new FutureTask[tasks.length]; for (int i = 0; i < tasks.length; i++) { futureTasks[i] = new FutureTask<>(tasks[i]); executorService.submit(futureTasks[i]); } // 获取任务结果 for (int i = 0; i < futureTasks.length; i++) { System.out.println("Result of task" + (i + 1) + ": " + futureTasks[i].get()); } // 关闭线程池 executorService.shutdown();
以下是程序的执行结果:

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

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

相关文章

深入浅出线程组和线程优先级

今天我们来简单的介绍一下线程组和线程的关系&#xff0c;以及线程优先级的相关内容。线程组(ThreadGroup)Java 用 ThreadGroup 来表示线程组&#xff0c;我们可以通过线程组对线程进行批量控制。每个 Thread 必然存在于一个 ThreadGroup 中&#xff0c;Thread 不能独立于 Thre…

Java主流连接池详解:特性、优缺点与适用场景

在Java应用开发中&#xff0c;数据库连接是稀缺资源。频繁创建和关闭连接会导致大量系统开销&#xff0c;降低应用性能。连接池技术通过预先创建一定数量的数据库连接并复用&#xff0c;有效解决了这一问题。本文将详细介绍Java生态中主流的数据库连接池&#xff0c;包括C3P0、…

基于企业数据构建可扩展AI:Nemotron RAG与SQL Server 2025整合架构解析

在某中心Ignite 2025大会上&#xff0c;某中心SQL Server 2025的发布标志着企业级AI就绪数据库愿景的实现&#xff0c;为开发者提供了内置向量搜索和用于调用外部AI模型的SQL原生API等强大新工具。某机构已与某中心合作&#xff0c;将SQL Server 2025与某机构Nemotron RAG开源模…

学霸同款2026继续教育一键生成论文工具TOP9测评

学霸同款2026继续教育一键生成论文工具TOP9测评 2026年继续教育论文写作工具测评&#xff1a;为何需要一份权威榜单&#xff1f; 在当前继续教育领域&#xff0c;论文撰写已成为学员提升学历、获取证书的必经之路。然而&#xff0c;面对繁重的工作与学习压力&#xff0c;许多学…

Java版LeetCode热题100之搜索二维矩阵 II:从暴力到最优解的完整解析

Java版LeetCode热题100之搜索二维矩阵 II&#xff1a;从暴力到最优解的完整解析 本文全面剖析 LeetCode 第240题「搜索二维矩阵 II」&#xff0c;涵盖题目理解、多种解法实现、复杂度分析、面试技巧及实际应用场景。无论你是准备面试的新手&#xff0c;还是希望深入理解算法优化…

C/C++ 将char[] 打印成二进制

逐字节打印成二进制: void print_char_to_binary(char chr) {for (int i 7; i > 0;i--) {char bit (chr >> i) & 1;printf("%d", bit);}printf("\n"); }int main() {char data[] { 0x12,0x3a,0xff };int len 3;for (int i 0; i < len…

2小时,我搭了一套供应链全流程可视化系统,采购、计划、仓库终于对齐了

你是不是也遇到过这种情况&#xff1a;采购说“料已经下了”&#xff0c;计划说“等物料到位才能排产”&#xff0c;仓库说“根本没看到发货信息”……每天各自忙得团团转&#xff0c;用着各自的Excel表格&#xff0c;开完会都说没问题&#xff0c; 结果月底一核对&#xff0c;…

Java版LeetCode热题100之反转链表:从迭代到递归的全面解析

Java版LeetCode热题100之反转链表&#xff1a;从迭代到递归的全面解析 本文深入剖析 LeetCode 第206题「反转链表」&#xff0c;作为后端开发面试的高频必考题&#xff0c;我们将从基础概念到高级技巧&#xff0c;从代码实现到实际应用&#xff0c;全方位掌握这一经典算法。无论…

大模型知识库(1)什么是Claude Skills?

Claude Skills 是 Anthropic 为其大语言模型 Claude 推出的扩展功能模块&#xff0c;可以理解为 Claude 的 “插件” 或 “技能包”&#xff0c;能够让 Claude 在基础对话能力之上&#xff0c;具备特定场景下的专业能力&#xff0c;从而更好地解决复杂任务。一、 Claude Skills…

Java版LeetCode热题100之回文链表:从数组复制到快慢指针的深度解析

Java版LeetCode热题100之回文链表&#xff1a;从数组复制到快慢指针的深度解析 本文全面剖析 LeetCode 第234题「回文链表」&#xff0c;作为面试高频题&#xff0c;我们将深入探讨三种解法的优劣&#xff0c;重点掌握O(1)空间复杂度的最优解。无论你是算法新手还是经验丰富的开…

Java版LeetCode热题100之相交链表:从哈希到双指针的深度解析

Java版LeetCode热题100之相交链表&#xff1a;从哈希到双指针的深度解析 本文全面剖析 LeetCode 第160题「相交链表」&#xff0c;涵盖题目理解、多种解法实现、复杂度分析、面试技巧及实际应用场景。无论你是准备面试的新手&#xff0c;还是希望深入理解链表操作的老手&#x…

Java版LeetCode热题100之环形链表:从哈希表到Floyd判圈算法的深度解析

Java版LeetCode热题100之环形链表&#xff1a;从哈希表到Floyd判圈算法的深度解析 本文全面剖析 LeetCode 第141题「环形链表」&#xff0c;作为面试必考的经典问题&#xff0c;我们将深入探讨两种核心解法&#xff0c;并重点掌握O(1)空间复杂度的Floyd判圈算法。无论你是算法新…

码字1年,我测废了10个AI写小说软件,最后只推荐这5款小说软件生成器!

哈喽大家好&#xff0c;又是我&#xff01; 我之前分享了&#xff0c;后台收到超多私信&#xff0c;都在说&#xff1a;“博主&#xff0c;道理我都懂&#xff0c;但就是下不了笔&#xff01;” 我太懂了&#xff01;真的&#xff01;&#x1f926; 知道要列大纲&#xff0c;…

富文本控件怎样提升XHEDITOR对Word公式粘贴的兼容性?

企业网站Word粘贴与导入功能解决方案 项目概述与技术需求 作为山西IT行业的.NET工程师&#xff0c;我们近期接到一个企业网站后台管理系统的升级需求&#xff0c;主要目标是实现Word内容一键粘贴和文档导入功能。这个功能将极大提升客户的内容发布效率&#xff0c;特别是对于…

不得了!实力天玑AIGEO优化系统代理大揭秘

实力天玑AIGEO优化系统代理大揭秘在数字化营销不断发展的当下&#xff0c;天玑AIGEO优化系统在本地精准营销领域逐渐崭露头角。下面将深入剖析该系统领域的行业痛点、天玑AI互联网中心的技术方案以及应用效果。行业痛点分析当前天玑AIGEO优化系统领域面临着诸多技术挑战。在数字…

Java版LeetCode热题100之环形链表 II:从哈希表到Floyd判圈算法的深度解析

Java版LeetCode热题100之环形链表 II&#xff1a;从哈希表到Floyd判圈算法的深度解析 本文全面剖析 LeetCode 第142题「环形链表 II」&#xff0c;作为面试高频难题&#xff0c;我们将深入探讨两种核心解法&#xff0c;并重点掌握O(1)空间复杂度的Floyd判圈算法及其数学证明。无…

医院HIS系统怎样实现检验报告公式转XHEDITOR在线编辑?

打造Word内容一键转存的CMS新闻管理系统升级方案 大家好&#xff01;我是山西某校软件工程专业的一名大三学生&#xff0c;最近正在给我的CMS新闻管理系统添加一个酷炫的功能——Word内容一键转存&#xff01;&#x1f389; 需求分析 我需要给后台编辑器增加一个按钮&#x…

国防项目如何实现加密Word文档公式安全导入XHEDITOR?

企业网站Word粘贴与导入功能解决方案 作为山西IT行业的PHP工程师&#xff0c;我最近正在评估如何为企业网站后台管理系统集成Word粘贴和文档导入功能。以下是针对这一需求的详细技术分析方案。 需求分析 客户需要实现两个核心功能&#xff1a; Word粘贴功能&#xff1a;从W…

军工领域,JAVA大文件分块上传的示例代码是什么?

我&#xff0c;一个被大文件上传逼疯的大三狗&#xff0c;想和你唠唠毕业设计的血泪史 最近为了做毕业设计&#xff0c;我把头发薅掉了小半——老师要的是“能打”的文件管理系统&#xff0c;核心需求就一条&#xff1a;10G大文件上传&#xff0c;还要支持文件夹、断点续传、加…

站群系统如何处理PDF公式转存为XHEDITOR网页格式?

企业网站Word粘贴与导入功能解决方案 项目概述与技术需求 作为山西IT行业的.NET工程师&#xff0c;我们近期接到一个企业网站后台管理系统的升级需求&#xff0c;主要目标是实现Word内容一键粘贴和文档导入功能。这个功能将极大提升客户的内容发布效率&#xff0c;特别是对于…