今天看书,有关于 FutureTask 的介绍,感觉还蛮有意思的,可以用它来做一些比较花时间的事情。下面打个通俗的比方来说明一下它的用处:
比如,早上一大早的去公交站台等公交,但那该死的公交20分钟才一班。如果一直死等公交,那么这20分钟无疑就被浪费了。我们可以利用这20分钟,去买个韭菜饼,再买一盒豆浆,然后一边吃一边等。这样就明显提高了时间的利用率。
?
下面给出一个段简单的代码来说明一下它的使用:
?
class="java">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方法,返回的值始终是一样的。