(目录)
一、说明
Future和FutureTask的关系
- Future 是一个接口,无法直接创建对象,需配合线程池使用
.submit()
方法返回值Future
来保存执行结果;而使用.execute()
方法传入Runnable
接口无返回值 - FutureTask 是一个类,可以直接创建对象,其实现了
RunnableFuture
接口(继承Future
接口)
使用区别
- 就是一个接口和实现类的不同写法
二、理解
Future
-
java.util.concurrent
包下Future<V>
接口,对Runnable
或Callable
对象执行任务完成后获取执行结果
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;
}
-
mayInterruptRunning
表示是否中断执行中的线程 -
boolean cancel()
尝试取消任务的执行,如果任务已经完成或已被取消,则返回false;如果任务已经启动,将以中断执行线程的方式停止该任务,停止成功则返回true -
boolean isDone()
若任务完成,则返回true -
boolean isCancelled()
若任务在完成前取消,则返回true -
get()
获取执行结果,必须等待任务完成后才返回结果 -
get(long timeout, TimeUnit unit)
获取执行结果,timeout表示等待的最长时间,unit表示时间单位,在指定时间内还没获取到结果,则返回null
FutureTask
-
java.util.concurrent
包下实现RunnableFuture<V>
接口,可实现Runnable
接口执行线程,也可实现Future
接口获取执行结果
public class FutureTask<V> implements RunnableFuture<V> {
……
}
-
RunnableFuture
接口继承Runnable
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}
FutureTask执行状态
- 根据方法执行的时机,FutureTask可处于以下三种行状态
FutureTask方法执行示意图
-
.cancel(ture)
会中断线程停止任务,适用于长时间处于运行的任务,并且能够处理interruption -
.cancel(false)
会让线程正常执行至完成,并返回false,适用于未能处理interruption的任务,或者不清楚是否支持取消的任务,以及等待已经开始的任务执行完成
三、实现
1.实现接口
创建CallableThreadDemo
类实现Callable
接口
public class CallableThreadDemo implements Callable{
@Override
public String call() throws Exception {
System.out.println("Callable子线程: " +Thread.currentThread().getName()+ " 开启");
return "我是Callable子线程: " +Thread.currentThread().getName()+ " 产生的结果";
}
}
2.使用Future
创建CallableTest
类执行测试,将创建好的线程对象通过.submit()
方法提交到线程池去执行,线程执行后,返回值Future
可被拿到
public class CallableTest {
public static void main(String[] args) {
// 1.创建线程池
ExecutorService executorService = Executors.newSingleThreadExecutor();
// 2.创建Callable子线程对象任务
CallableThreadDemo callableThread_1 = new CallableThreadDemo();
// 3.提交任务到线程池
Future future = executorService.submit(callableThread_1);
// 4.获取执行结果
try {
System.out.println("主线程开始执行");
System.out.println("主线程要取得Callable子线程的结果");
if (future.get()!=null){
//输出获取的结果
System.out.println(future.get());
}else {
//输出未获取到结果
System.out.println("future.get()未获取到结果");
}
} catch (InterruptedException e){
e.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
}
// 5.关闭线程池
executorService.shutdown();
System.out.println("主线程执行完成");
}
}
3.使用FutureTask
创建FutureTask
对象,提交任务到线程池,可以交给Executor
执行,或将创建好的线程对象通过.submit()
方法提交到线程池去执行,线程执行后,返回值FutureTask
可被拿到
public class CallableTest {
public static void main(String[] args) {
// 1.创建线程池
ExecutorService executorService = Executors.newSingleThreadExecutor();
// 2.创建Callable子线程对象任务
CallableThreadDemo callableThread_1 = new CallableThreadDemo();
// 3.提交任务到线程池
FutureTask futureTask = new FutureTask(callableThread_1);
executorService.submit(futureTask);
// 4.获取执行结果
try {
System.out.println("主线程开始执行");
System.out.println("主线程要取得Callable子线程的结果");
if (futureTask.get()!=null){
//输出获取的结果
System.out.println(futureTask.get());
}else {
//输出未获取到结果
System.out.println("futureTask.get()未获取到结果");
}
} catch (InterruptedException e){
e.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
}
// 5.关闭线程池
executorService.shutdown();
System.out.println("主线程执行完成");
}
}