Future的使用
情景:
我们使用如下方式进行线程处理时是无法获取线程的执行结果的。这里我们将程序执行结果赋给result
。但是如下程序在编译期间就报错了,因为内部类访问局部变量需要使用final作为修饰符。所以如下方式是不行的。
public static void main(String[] args) {
String result = "这是一个初始值";
new Thread(()->{
// 线程处理逻辑
result = "这个是执行的结果";
});
System.out.println(result);
}
换一种思路,获取线程执行结果的值。
package mythread;
public class Test {
public static void main(String[] args) {
String result = "这是一个初始值";
MyThread myThread = new MyThread();
new Thread(myThread).start();
System.out.println(myThread.getResult());
while (myThread.isSuccess() == true) {
System.out.println(myThread.getResult());
System.out.println(result);
break;
}
}
}
class MyThread implements Runnable {
private String result;
private boolean success = false;
@Override
public void run() {
result = "程序执行结果";
success = true;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
}
上面这个方法需要写一个实现Runable接口的类,在类中定义一个标志线程执行结束的变量success。main函数里使用该类启动线程。
使用该方法就可以获取线程执行结果。但是有点笨重。其实我主要的业务代码就三四行,却要写一大通需要依赖的代码来实现。性价比也忒低。
下面我们的主角Future
就登场了。
Future
使用Future我们可以很容易的获取线程返回的结果。
public static void main(String[] args) {
ExecutorService es = Executors.newFixedThreadPool(3);
Future<String> future = es.submit(()->{
return "程序执行结束";
});
try {
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
Future是一个接口,一般可以通过Executors类实例化出来一个特定的线程池实例对象并调用submit方法得到相应的实例。
注意Future的get方法是线程阻塞的。
future.get(1, TimeUnit.SECONDS);
指定获取结果的时间,第二个参数为时间单位。上面的方法也就是一秒后获取结果。如果指定时间内线程没有返回,则会抛出TimeoutException
异常。
future中可以使用isDone
来判断线程是否结束。
isCancelled
判断线程是否在结束之前被取消。
cancel
用来停止一个运行中的线程。如果线程不能被停止则返回false,一般情况下是线程已经 执行结束。线程停止则返回true。