Java 1.5开始, 提供了 Callable
和 Future
, 经过它们能够在任务执行完毕以后获得任务执行结果.多线程
当须要调用几个执行很慢的方法时, 可使用多线程一块儿执行这几个方法, 等全部方法执行完毕后获得执行结果, 在进行别的处理.dom
Future 的主要方法ide
Future
接口主要包括 5 个方法:spa
get()
方法能够当任务结束后返回一个结果, 若是调用时, 工做尚未结束, 则会阻塞线程, 直到任务执行完毕.线程
get(long timeout,TimeUnit unit)
作多等待 timeout
的时间就会返回结果.3d
cancel(boolean mayInterruptIfRunning)
方法能够用来中止一个任务.code
isDone()
方法判断当前方法是否完成.blog
isCancel()
方法判断当前方法是否取消.接口
Future 示例 demo游戏
需求场景: 等早餐过程当中, 包子须要 3 秒, 凉菜须要 1 秒, 普通的多线程须要四秒才能完成. 先等凉菜, 再等包子, 由于等凉菜时, 普通多线程启动 start()
方法, 执行 run()
中具体方法时, 没有返回结果, 因此若是要等有返回结果, 必须是要1秒结束后才知道结果.
public static void main(String[] args) throws InterruptedException, ExecutionException { long start = System.currentTimeMillis(); // 等凉菜 Callable ca1 = new Callable() { @Override public String call() throws Exception { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } return "凉菜准备完毕"; } }; FutureTask<String> ft1 = new FutureTask<String>(ca1); new Thread(ft1).start(); // 等包子 -- 必需要等待返回的结果,因此要调用join方法 Callable ca2 = new Callable() { @Override public Object call() throws Exception { try { Thread.sleep(1000 * 3); } catch (InterruptedException e) { e.printStackTrace(); } return "包子准备完毕"; } }; FutureTask<String> ft2 = new FutureTask<String>(ca2); new Thread(ft2).start(); System.out.println(ft1.get()); System.out.println(ft2.get()); long end = System.currentTimeMillis(); System.out.println("准备完毕时间:" + (end - start)); }
还有一个比较典型的例子就是设置超时时间:
//固定大小的线程池,同时只能接受5个任务 static ExecutorService mExecutor = Executors.newFixedThreadPool(5); final static long timeout = 4 ; /** * 模拟在预约时间内获取广告信息 * @throws InterruptedException */ static void rederPageWithAd(final String pageTitle) throws InterruptedException{ Future<String> f = mExecutor.submit(new Callable<String>() { @Override public String call() throws Exception { System.out.println("开始加载广告信息"); int randomTime = new Random().nextInt(5) + 1;//限制耗时不会出现0s,不会大于10s Thread.sleep(100 * 1000); System.out.println("正常加载广告耗时:" + randomTime +"s"); return pageTitle; } }); String page; try { //在预计时间内等待 System.out.println("预期任务执行完时间:" + timeout + "s"); //page = f.get(); page = f.get(timeout, TimeUnit.SECONDS); } catch (ExecutionException e) { page = "出现执行异常,显示默认的广告页面"; } catch (TimeoutException e) { page = "任务执行超时,显示默认的广告页面"; f.cancel(true);//取消没有执行完的任务,设置为ture说明任务能被中断,不然执行中的任务要完成 } System.out.println("成功加载广告页面:" + page); } public static void main(String[] args) { try { List<String> titleList = new ArrayList<String>(); titleList.add("体育赛事"); titleList.add("娱乐新闻"); titleList.add("实时聚焦"); titleList.add("国际咨询"); titleList.add("影视天下"); titleList.add("游戏风云"); for (String string : titleList) { rederPageWithAd(string); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally{ /** * 只有执行了shutdown方法,执行isTerminated才有效。不然isTerminated一直为ture */ mExecutor.shutdown(); while(true){ if(mExecutor.isTerminated()){ System.out.println("全部任务都执行完了,关闭线程池"); break; } } } }
值得注意的是: 当主线程调用 Future
的 get
方法的时候会获取到从线程中返回的结果数据. 若是在线程的执行过程当中发生了异常, get
会获取到异常的信息.