1.简介
Callable是一个接口,与Runnable类似,包含一个必须实现的call方法,可以启动为让另一个线程来执行,执行Callable可以得到一个Future对象 该对象可以监听Callable的执行结果 也可以取消该任务的执行
2.案例
package org.lkl.thead.foo; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class CallableAndFuture { public static void main(String[] args) throws InterruptedException, ExecutionException { ExecutorService threadPool = Executors.newSingleThreadExecutor() ; Future<String> future = threadPool.submit(new Callable<String>() { @Override public String call() throws Exception { System.out.println("call method"); Thread.sleep(100) ; return "liaokailin"; } }) ; System.out.println(" future.isCancelled():"+ future.isCancelled()); ; while(!future.isDone()){ System.out.println("---等待结果---"); } // future.cancel(true) ; System.out.println(future.get() );; } }
通过threadPool.submit可以返回一个Future对象 ,通过该对象的 future.isDone 表示Callable中的任务是否执行完成 true表示完成
future.cancle(true) 可以取消Callable中的任务(call)
future.get() 得到的是Callable中call方法的返回值.
注意 代码执行到future.get()的时候会等待Callable中的call方法执行 等待执行结束以后get()方法才会执行完成 ,否则一直在等待call的执行 也可以通过 future.get(timeout, unit)
方法来设置等待几秒以后获取call的返回值 如果没有获取到结果则返回异常.
3. CompletionService
通过CompletionService可以处理一组Callable任务 ,通过其take方法可以获得Future对象
ExecutorService threadPool = Executors.newFixedThreadPool(10) ; CompletionService<Integer> service = new ExecutorCompletionService<Integer>(threadPool) ; for(int i =1 ;i<=10;i++){ final int flag = i ; service.submit(new Callable<Integer>() { @Override public Integer call() throws Exception { Thread.sleep(new Random().nextInt(1000)) ; return flag; } }) ; } for(int i =1 ;i<=10;i++){ Future<Integer> future = service.take() ; System.out.println(future.get() ); }
结果:
8 1 5 3 2 10 6 4 9 7
执行的结果是无序的 那么说明CompletionService获得Callable的结果是 看哪个Callable先执行完成则先获得其返回的结果
如果将上面的 ExecutorService threadPool = Executors.newFixedThreadPool(10) ; 方法换成:
ExecutorService threadPool = Executors.newSingleThreadExecutor() ;
则执行的结果是从1-10有序的
那是因为当前线程池中只有一个线程 要等待for循环的第一次执行完才会去执行第二次的for循环.