今天看书,有关于 FutureTask 的介绍,感觉还蛮有意思的,可以用它来做一些比较花时间的事情。下面打个通俗的比方来说明一下它的用处:
比如,早上一大早的去公交站台等公交,但那该死的公交20分钟才一班。如果一直死等公交,那么这20分钟无疑就被浪费了。我们可以利用这20分钟,去买个韭菜饼,再买一盒豆浆,然后一边吃一边等。这样就明显提高了时间的利用率。
下面给出一个段简单的代码来说明一下它的使用:
public class Preloader {
private final FutureTask<Long> future = new FutureTask<Long>(new Callable<Long>() {
@Override
public Long call() throws Exception {
Thread.currentThread().setName("Thread(3)");
System.out.println(Thread.currentThread().getName() + ": simulate a latency ");
try {
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ": the latency is over");
return Math.round(Math.random() * 1000);
}
});
private final Thread loader = new Thread(future);
public void start() {
System.out.println(Thread.currentThread().getName() + ": start the loader");
loader.start();
System.out.println(Thread.currentThread().getName() + ": loader started");
}
public Long get() {
try {
System.out.println(Thread.currentThread().getName() + ": begin to get");
long start = System.currentTimeMillis();
Long result = future.get();
System.out.println(Thread.currentThread().getName() + ": got result: " + result);
System.out.println(Thread.currentThread().getName() + ": spent time: "
+ (System.currentTimeMillis() - start));
return result;
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ": got nothing");
return null;
}
public static void main(String[] args) {
Thread.currentThread().setName("Thread(main)");
final Preloader pl = new Preloader();
pl.start();
// try to get the result before the latency is over
new Thread(new Runnable() {
@Override
public void run() {
Thread.currentThread().setName("Thread(1)");
pl.get();
}
}).start();
// try to get the result after the latency is over
new Thread(new Runnable() {
@Override
public void run() {
Thread.currentThread().setName("Thread(2)");
try {
Thread.sleep(6000);
pl.get();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
以上代码的运行结果为:
main: start the loader main: loader started Thread(3): simulate a latency Thread(1): begin to get Thread(3): the latency is over Thread(1): got result: 917 Thread(1): spent time: 5006 Thread(2): begin to get Thread(2): got result: 917 Thread(2): spent time: 0
通过上面运行的结果,我们可以得到以下结论:
① 在FutureTask执行完了之前(即call执行完了之前),去进行get的话,将被会一直阻塞至FutureTask执行完了才会返回。
② FutureTask执行完了之后,再调用get的话,会立刻返回相应的结果
③ FutureTask只会执行一次,所以,多次调用get方法,返回的值始终是一样的。