Future往往出现在Java多线程代码当中,从字面意思理解——“未来”。它表达的是当下不能立即得到,未来才会得到的结果,细想一下,这和多线程的思路很吻合。在Java开发中,我们往往会将比较耗时,占用主线程资源的工作,丢给子线程做,比如我们在网络上爬取房产信息,这个爬取的过程可能很长且工作量巨大,那么我们可以创建多个线程,每个线程负责不同的站点,由于耗费时间较长,在启动子线程爬取之后不能立即获得结果,这时候,我们就可以将结果封装到Future中以表示未来才会获取的返回。
在Java api文档中对Future的定义是这样的:
public interface Future<V>
A Future represents the result of an asynchronous computation. Methods are provided to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation. The result can only be retrieved using method get when the computation has completed, blocking if necessary until it is ready. Cancellation is performed by the cancel method. Additional methods are provided to determine if the task completed normally or was cancelled. Once a computation has completed, the computation cannot be cancelled. If you would like to use a Future for the sake of cancellability but not provide a usable result, you can declare types of the form Future<?> and return null as a result of the underlying task.
这段话很好理解,中心思想是:接口Future代表了异步计算的结果,它的方法包括
- isDone:用来判断异步结构是否回传给Future;
- get:获取异步回传的结果,调用get后,程序会一直等到有结果返回后才会向下执行,换一句话说get会造成线程堵塞,所以说我们一般会先进行isDone判断后再执行get;
- isCancelled:判断程序所执行的异步任务是否在正常结束前被取消;
- cancel:取消当前正在进行的task;
现有这样一个例子:存在一个计算平方的方法caculate,我们为了能够看到future的效果,在这个方法中增加2s的延时。其中Executors.newFixedThreadPool用来创建固定线程数目的线程池,本例线程数为2。
public class SquareCalculator {
private ExecutorService executorService = Executors.newFixedThreadPool(2);
public Future<Integer> caculate(int input) {
return executorService.submit(() -> {
Thread.sleep(2000);
return input * input;
});
}
}
然后我们在Main方法中调用两次平方计算方法,期间间隔1s,在两个线程都没有完成期间,每个3ms打印一次线程完成情况。
public class Main {
public static void main(String[] args) throws InterruptedException, ExecutionException {
SquareCalculator squareCalculator = new SquareCalculator();
Future<Integer> future1 = squareCalculator.caculate(2);
Thread.sleep(1000);
Future<Integer> future2 = squareCalculator.caculate(3);
while (!(future1.isDone() && future2.isDone())) {
out.println(String.format(
"future1 is %s and future2 is %s",
future1.isDone() ? "done" : "not done",
future2.isDone() ? "done" : "not done"
));
Thread.sleep(300);
}
out.println("2*2 equal to " + future1.get() + " and 3*3 equal to " + future2.get());
}
}
最终结果:
结果
可见我们可以通过对Future的isDone来判断线程是否完成。
网友评论