前言
在java并发编程领域,futuretask扮演着举足轻重的角色,它不仅能够实现可取消的异步运算,还提供了丰富的状态查询与结果获取功能。本文旨在剖析futuretask的核心概念及其灵活的使用方法,帮助开发者全面理解其工作机制。文章还将通过一个java代码案例,展示如何借助executorservice启动并管理futuretask任务。
一、futuretask简介
futuretask是java并发编程中的一个关键组件,它代表了一个可以取消的异步运算任务。该任务不仅具备异步执行的能力,还提供了丰富的操作接口以满足不同的并发需求。以下是futuretask所提供的核心方法:
启动运算:
方法为void run(),由runnable接口继承而来,但futuretask实际是通过callable或runnable的包装来执行具体运算。虽然futuretask本身实现了runnable接口,但通常不直接调用其run方法,启动futuretask的任务是通过将其提交给executor(如executorservice的submit方法)来实现的,而futuretask的run方法会在内部被调用以执行运算。
callable<string> callable = () -> "task result"; futuretask<string> futuretask = new futuretask<>(callable); executorservice executorservice = executors.newsinglethreadexecutor(); executorservice.submit(futuretask);
取消运算:
通过调用cancel(boolean mayinterruptifrunning)方法,可以中断正在执行的任务。若mayinterruptifrunning为true,则尝试中断正在运行的任务,若为false,则仅当任务尚未启动时才能成功取消。如果任务成功被取消,则返回true,否则返回false(表示任务可能已经完成或无法被取消)。
// 尝试中断正在运行的任务 boolean cancelled = futuretask.cancel(true);
查询运算是否完成:
通过isdone()方法,可以查询任务是否已经完成。该方法返回一个布尔值,表示任务是否已经完成(包括正常结束、异常终止或被取消),如果任务已经完成,则返回true,否则返回false。
// 查询任务是否完成 boolean iscompleted = futuretask.isdone();
取回运算结果:
当任务完成后,可通过get()方法和get(long timeout, timeunit unit)方法获取运算结果。对于带超时的get(long timeout, timeunit unit)方法,timeout表示等待结果的最大时间量,unit表示timeout参数的时间单位。若任务尚未完成,调用get()方法将会阻塞当前线程,直至任务完成或抛出异常(如interruptedexception、executionexception)。
如果当前线程在等待结果时被中断,则抛出interruptedexception;如果任务抛出了异常,则抛出executionexception;如果在指定的等待时间内没有获取到结果(仅对于带超时的get方法)则抛出timeoutexception。
try { // 获取运算结果,若任务未完成则阻塞 string result = futuretask.get(); } catch (interruptedexception | executionexception e) { // 处理异常 e.printstacktrace(); }
futuretask的显著特点是,其运算结果只有在任务完成后才能被安全地取回。若任务尚未完成,任何对get方法的调用都将导致调用线程阻塞,直至任务执行完毕或抛出异常。这种机制确保了数据的完整性和线程的安全性。
二、futuretask的使用
futuretask能够对callable和runnable对象进行包装,从而允许这些任务异步执行,并且能够获取任务的执行结果。由于futuretask实现了runnable接口,因此它可以被提交给executor(如executorservice)来执行。
以下是使用futuretask的步骤:
1.创建callable或runnable任务对象:
- 若需要获取任务执行的结果,则应创建一个callable对象,并实现其call方法,该方法包含了具体的任务逻辑,并返回一个结果。
- 若任务不需要返回结果,则可以创建一个runnable对象,并实现其run方法,该方法包含了具体的任务逻辑。
2.创建futuretask对象:
- 使用上一步创建的callable或runnable对象作为参数,来初始化一个futuretask对象。futuretask的构造函数接受一个callable或runnable参数,并根据传入的参数类型来执行相应的逻辑。
3.将futuretask对象提交给executorservice执行:
- 创建一个executorservice对象,该对象负责管理线程池中的线程。
- 使用executorservice的submit方法将futuretask对象提交给线程池执行。submit方法会返回一个future对象,该对象可以用于检查任务是否完成、等待任务完成以及获取任务的结果。由于futuretask实现了future接口,因此submit方法返回的future对象实际上就是之前提交的futuretask对象。
4.调用futuretask的get方法获取运算结果:
- 在任务提交后,可以调用futuretask对象的get方法来获取任务的执行结果。如果任务尚未完成,get方法会阻塞当前线程,直到任务完成并返回结果。如果任务执行过程中抛出异常,get方法会将该异常封装为一个executionexception并抛出。
- 虽然futuretask提供了获取任务结果的能力,但在实际开发中,通常推荐使用executorservice的submit方法返回的future对象来获取结果,这样可以避免直接操作futuretask对象,使代码更加清晰和易于维护。并且在使用futuretask时,还需要注意线程安全和异常处理等问题(例如,应确保在调用get方法之前任务已经提交给executorservice执行,并应妥善处理可能抛出的executionexception等异常)。
三、代码案例
以下代码案例展示了如何运用futuretask来异步执行callable任务,并获取其执行结果。
import java.util.concurrent.*; public class futuretaskexample { public static void main(string[] args) { // 定义一个callable任务,该任务会返回一个字符串结果 callable<string> callabletask = new callable<string>() { @override public string call() throws exception { // 使用thread.sleep(2000)来模拟耗时2秒的操作 thread.sleep(2000); // 返回操作结果 return "futuretask任务已完成"; } }; // 使用callable任务初始化一个futuretask对象 // futuretask不仅实现了runnable接口,还实现了future接口,这意味着它可以被提交给executor执行,并且能够获取执行结果 futuretask<string> futuretask = new futuretask<>(callabletask); // 使用executors.newsinglethreadexecutor()创建了一个单线程的executorservice来管理线程池 executorservice executorservice = executors.newsinglethreadexecutor(); // 将futuretask提交给executorservice执行 // submit方法会返回一个future对象,由于提交的是futuretask对象,因此返回的future对象是futuretask本身 executorservice.submit(futuretask); try { // 调用futuretask的get方法来获取执行结果 // 如果任务尚未完成,get方法会阻塞当前线程直到任务完成,如果任务执行过程中抛出异常,get方法会抛出executionexception string result = futuretask.get(); // 输出结果 system.out.println(result); } catch (interruptedexception | executionexception e) { // 处理可能的异常 e.printstacktrace(); } finally { // 关闭executorservice,释放资源 executorservice.shutdown(); } } }
在此案例中定义了一个callable任务,该任务会模拟一个耗时操作,并在操作完成后返回一个字符串结果。接着,使用这个callable任务初始化了一个futuretask对象,并创建了一个executorservice来管理线程池,并将futuretask提交给executorservice执行。最后调用futuretask的get方法来获取执行结果,并输出结果到控制台。在任务执行完毕后关闭了executorservice以释放资源。
运行结果:
总结
本文介绍了futuretask在java并发编程中的关键作用。futuretask结合了callable与future接口,实现了异步运算的高效提交与结果获取。通过具体代码示例,展示了如何利用futuretask与executorservice执行异步任务。掌握futuretask不仅能提升程序响应速度与执行效率,还能在复杂多线程环境中协调异步运算,实现运算进度的监控与异常处理。因此,futuretask是构建高性能并发程序的重要工具,对于开发响应式系统及处理并行计算任务具有显著优势。
到此这篇关于java并发编程:futuretask解析与实战的文章就介绍到这了,更多相关java futuretask内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论