Callable接口類(lèi)似于Runnable,從名字就可以看出來(lái)了,但是Runnable不會(huì )返回結果,并且無(wú)法拋出返回結果的異常,而Callable功能更強大一些,被線(xiàn)程執行后,可以返回值,這個(gè)返回值可以被Future拿到,也就是說(shuō),Future可以拿到異步執行任務(wù)的返回值,下面來(lái)看一個(gè)簡(jiǎn)單的例子:
- public class CallableAndFuture {
- public static void main(String[] args) {
- Callable<Integer> callable = new Callable<Integer>() {
- public Integer call() throws Exception {
- return new Random().nextInt(100);
- }
- };
- FutureTask<Integer> future = new FutureTask<Integer>(callable);
- new Thread(future).start();
- try {
- Thread.sleep(5000);// 可能做一些事情
- System.out.println(future.get());
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
- }
- }
FutureTask實(shí)現了兩個(gè)接口,Runnable和Future,所以它既可以作為Runnable被線(xiàn)程執行,又可以作為Future得到Callable的返回值,那么這個(gè)組合的使用有什么好處呢?假設有一個(gè)很耗時(shí)的返回值需要計算,并且這個(gè)返回值不是立刻需要的話(huà),那么就可以使用這個(gè)組合,用另一個(gè)線(xiàn)程去計算返回值,而當前線(xiàn)程在使用這個(gè)返回值之前可以做其它的操作,等到需要這個(gè)返回值時(shí),再通過(guò)Future得到,豈不美哉!這里有一個(gè)Future模式的介紹:
http://caterpillar.onlyfun.net/Gossip/DesignPattern/FuturePattern.htm。
下面來(lái)看另一種方式使用Callable和Future,通過(guò)ExecutorService的submit方法執行Callable,并返回Future,代碼如下:
- public class CallableAndFuture {
- public static void main(String[] args) {
- ExecutorService threadPool = Executors.newSingleThreadExecutor();
- Future<Integer> future = threadPool.submit(new Callable<Integer>() {
- public Integer call() throws Exception {
- return new Random().nextInt(100);
- }
- });
- try {
- Thread.sleep(5000);// 可能做一些事情
- System.out.println(future.get());
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
- }
- }
代碼是不是簡(jiǎn)化了很多,ExecutorService繼承自Executor,它的目的是為我們管理Thread對象,從而簡(jiǎn)化并發(fā)編程,Executor使我們無(wú)需顯示的去管理線(xiàn)程的生命周期,是JDK 5之后啟動(dòng)任務(wù)的首選方式。
執行多個(gè)帶返回值的任務(wù),并取得多個(gè)返回值,代碼如下:
- public class CallableAndFuture {
- public static void main(String[] args) {
- ExecutorService threadPool = Executors.newCachedThreadPool();
- CompletionService<Integer> cs = new ExecutorCompletionService<Integer>(threadPool);
- for(int i = 1; i < 5; i ) {
- final int taskID = i;
- cs.submit(new Callable<Integer>() {
- public Integer call() throws Exception {
- return taskID;
- }
- });
- }
- // 可能做一些事情
- for(int i = 1; i < 5; i ) {
- try {
- System.out.println(cs.take().get());
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
- }
- }
- }
其實(shí)也可以不使用CompletionService,可以先創(chuàng )建一個(gè)裝Future類(lèi)型的集合,用Executor提交的任務(wù)返回值添加到集合中,最后便利集合取出數據,代碼略。
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請
點(diǎn)擊舉報。