一、FutureTask的实现
FutureTask实现了RunnableFuture,既即实现Runnable接口和Future接口。所以FutureTask实现run方法,以及Future接口的一系列计算结果方法
二、构造方法
FutureTask有两个构造方法,分别为一个参数和两个参数,如下图:
一个参数构造器传入一个Callable实现,需要返回参数;
第二个构造器第一个参数传入Runnable实现,不需要返回参数,但是需要再第二个参数指定返回值;
如下:
public static void test1() throws Exception {
// FutureTask封装一个线程
FutureTask<String> future = new FutureTask<>(() -> {
System.out.println("work...");
Thread.sleep(3000);
throw new Exception("神奇");
// return "工作完成";
});
// run运行线程,不会返回结果,线程异常不会被抛出,get时才会抛出异常
future.run();
// get等待任务执行完成,并返回结果
System.out.println(future.get());
}
public static void test2() throws Exception {
FutureTask<String> futureTask = new FutureTask<>(() -> System.out.println("work"), "OK");
futureTask.run();
System.out.println(futureTask.get());
}
三、方法
1、run():同线程的run方法,执行FutureTask的线程run方法,该方法不会抛出线程内部的异常。如果在之前FutureTask已被调用cancle方法取消,会抛出CancellationException。注意,FutureTask直接执行run方法,会阻塞等待线程执行完成,如下:
public static void testRun() throws Exception {
FutureTask<String> future = new FutureTask<>(() -> {
System.out.println("work...");
Thread.sleep(5000);
return "工作完成";
});
future.run();
System.out.println("主线程被阻塞");
System.out.println(future.get());
}
如果需要异步执行,需要用new Thread()去跑或者通过线程池执行,如下:
public static void testRun() throws Exception {
FutureTask<String> future = new FutureTask<>(() -> {
System.out.println("work...");
Thread.sleep(5000);
return "工作完成";
});
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(future);
System.out.println("主线程不被阻塞");
System.out.println(future.get());
System.out.println("主线程阻塞,get等线程返回结果");
}
2、cancle方法:尝试取消执行此任务,有一个布尔值的参数mayInterruptIfRunning,此参数决定是否可以终止正在执行中的线程。
mayInterruptIfRunning为true,可以终止正在执行中的线程,返回true;
public static void testCancle() throws Exception { FutureTask<String> future = new FutureTask<>(() -> { System.out.println("work..."); for (int i = 0; i < 10; i++) { Thread.sleep(1000); System.out.println(i); } System.out.println("工作完成!!!!"); return "工作完成"; }); Thread thread = new Thread(future); thread.start(); Thread.sleep(1000); System.out.println("取消正在执行的FutureTask"); //true,会终止正在运行的线程 System.out.println(future.cancel(true)); System.out.println(future.isCancelled()); }
mayInterruptIfRunning为false,不能终止正在执行中的线程,返回false;
public static void testCancle() throws Exception { FutureTask<String> future = new FutureTask<>(() -> { System.out.println("work..."); for (int i = 0; i < 10; i++) { Thread.sleep(1000); System.out.println(i); } System.out.println("工作完成!!!!"); return "工作完成"; }); Thread thread = new Thread(future); //false,如果线程已经开始执行,当前任务是不会被终止,但是仍然返回true System.out.println("取消还未执行的FutureTask"); System.out.println(future.cancel(false)); System.out.println(future.isCancelled()); thread.start(); }
- 如果线程已被cancle,再次cancle将返回false;
public static void testCancle() throws Exception { FutureTask<String> future = new FutureTask<>(() -> { System.out.println("work..."); Thread.sleep(5000); return "工作完成"; }); new Thread(future).start(); System.out.println("取消正在执行的FutureTask"); System.out.println(future.cancel(true)); System.out.println(future.get()); }
3、get方法:等待计算完成,然后检索其结果,这个方法会阻塞主线程,直到run执行完成并返回值。还可以设置最长等待时间,超过将抛出TimeoutException;计算引发异常抛出ExecutionException;当前线程在等待时中断抛出InterruptedException;计算被取消抛出CancellationException。
public static void testTimeoutException() throws Exception {
FutureTask<String> future = new FutureTask<>(() -> {
System.out.println("work...");
Thread.sleep(5000);
System.out.println("工作完成!!!!");
return "工作完成";
});
new Thread(future).start();
System.out.println(future.get(1, TimeUnit.SECONDS));
}
public static void testCancellationException() throws Exception {
FutureTask<String> future = new FutureTask<>(() -> {
System.out.println("work...");
Thread.sleep(5000);
System.out.println("工作完成!!!!");
return "工作完成";
});
new Thread(future).start();
Thread.sleep(1000);
System.out.println(future.cancel(true));
System.out.println(future.get(1, TimeUnit.SECONDS));
}
public static void testGetExecutionException() throws Exception {
FutureTask<String> future = new FutureTask<>(() -> {
System.out.println("work...");
throw new Exception("出错啦");
});
new Thread(future).start();
System.out.println(future.get());
}
public static void testInterruptedException() throws Exception {
FutureTask<String> future = new FutureTask<>(() -> {
System.out.println("work...");
Thread.sleep(5000);
return "工作完成";
});
Thread thread = new Thread(future);
thread.start();
thread.interrupt();
System.out.println(future.get());
}