FutureTask的使用场景
针对如果有多个需要返回结果且耗时的流程的场景。
例如,A和B两个方法都耗时500ms。且都需要获取到这两个方法的返回值。如果不使用异步则需要1000ms。但是使用异步任务同时执行这两个方法,则只需要500ms
创建线程的几种方式:
-
实现Callable接口,重写call()方法,将所要完成的任务的代码写进call()方法中,需要注意的是call()方法有返回值,并且可以抛出异常。
-
实现Runnable接口,重写run()方法,将所要完成的任务代码写进run()方法中。
-
继承Thread类或直接创建Thread类对象。
FutureTask的构造方法
java.util.concurrent.FutureTask.FutureTask(Callable<V> callable)
该方法需要传入一个Callable接口的实例对象。V是返回值的类型
FutureTask常用方法讲解
isDone():判断任务是否执行结束,正常执行结束,或者发生异常结束,或者被取消,都属于结束,该方法都会返回true
cancel(boolean mayInterruptIfRunning):取消子任务的执行,
如果这个子任务已经执行结束,或者已经被取消,或者不能被取消,这个方法就会执行失败并返回false;
如果子任务还没有开始执行,那么子任务会被取消,不会再被执行;
如果子任务已经开始执行了,但是还没有执行结束,根据mayInterruptIfRunning的值,
如果mayInterruptIfRunning = true,那么会中断执行任务的线程,然后返回true,
如果参数为false,会返回true,不会中断执行任务的线程
V get():获取结果,如果这个计算任务还没有执行结束,该调用线程会进入阻塞状态。
如果计算任务已经被取消,调用get()会抛出CancellationException,
如果计算过程中抛出异常,该方法会抛出ExecutionException,
如果当前线程在阻塞等待的时候被中断了,该方法会抛出InterruptedException
V get(long timeout, TimeUnit unit):带超时限制的get(),等待超时之后,该方法会抛出TimeoutException
FutureTask使用Demo
call_A和call_B两个方法都耗时5000ms。且都需要获取到这两个方法的返回值。将这两个耗时的操作放到FutureTask中异步执行,并使用get()获取其返回值。
package com.study.test;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
*
* @描述: Future 使用 参考 https://www.jianshu.com/p/55221d045f39
* @版权: Copyright (c) 2020
* @公司:
* @作者: 严磊
* @版本: 1.0
* @创建日期: 2020年6月28日
* @创建时间: 下午5:21:54
*/
public class FutureTaskDemo
{
public static void main(String[] args) throws InterruptedException, ExecutionException
{
long startTime = System.currentTimeMillis();
// 第一步:使用一个单独的线程执行一个耗时的操作A,并返回执行结果
Callable<String> call_A = new Callable<String>()
{
@Override
public String call() throws Exception
{
System.out.println(" A开始执行耗时的操作");
Thread.sleep(5000);
System.out.println(" A执行耗时的操作完成");
return "耗时的操作执行结果AAAAA";
}
};
FutureTask<String> task_A = new FutureTask<String>(call_A);
System.out.println("启动异步任务流程A");
new Thread(task_A).start();
// 第二步:使用一个单独的线程执行一个耗时的操作B,并返回执行结果
Callable<String> call_B = new Callable<String>()
{
@Override
public String call() throws Exception
{
System.out.println(" B开始执行耗时的操作");
Thread.sleep(5000);
System.out.println(" B执行耗时的操作完成");
return "耗时的操作执行结果BBBBB";
}
};
FutureTask<String> task_B = new FutureTask<String>(call_B);
System.out.println("启动异步任务流程B");
new Thread(task_B).start();
// isDone() 检查A、B任务是否执行完成。任务正常终止、异常或取消,该方法都返回true
if ( !task_A.isDone() || !task_B.isDone())
{
if( !new Random().nextBoolean())
{
System.out.println("取消执行耗时的操作");
// cancel() 尝试取消任务
task_A.cancel(true);
task_B.cancel(true);
return;
}
}
//第三步:获取异步执行的结果,get()方法会阻塞调用线程,直到异步任务执行完成
String result_A = task_A.get();
String result_B = task_B.get();
System.out.println("A返回的结果:"+result_A);
System.out.println("B返回的结果:"+result_B);
System.out.println("总共用时" + (System.currentTimeMillis() - startTime) + "ms");
}
}
执行结果:
可以看到这两个任务是并行执行的。只消耗了5002ms

本文详细介绍了如何在Java中使用FutureTask进行并行任务处理,通过A、B两个耗时5秒的方法示例,展示了如何通过异步执行和get()获取结果,显著减少总耗时。
1013

被折叠的 条评论
为什么被折叠?



