启动一个线程不论使用Thread或者Runnable的时候,都是没有返回结果的。也就是说Thread和Runnable的run()方法必须没有返回值。
public void run(){}
解决方案:
Callable和Future,一个产生结果,一个拿到结果。
简单的来一个实例demo帮助我们理解:
public class CallableAndFuture { /** * @param args */ public static void main(String[] args) { //单一线程的线程池 ExecutorService threadPool = Executors.newSingleThreadExecutor(); Future<String> future = threadPool.submit( new Callable<String>() { public String call() throws Exception { Thread.sleep(2000); return "hello"; }; } ); System.out.println("等待结果"); try { System.out.println("拿到结果" + future.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } }
执行结果:
等待结果
拿到结果hello
使用场景:
假设有一个很耗时的返回值需要计算,并且这个返回值不是立刻需要的话,那么就可以使用以上这种方式,用另一个线程去计算返回值,而当前线程在使用这个返回值之前可以做其它的操作,等到需要这个返回值时,再通过Future得到!
说明:
Future取得的结果类型和Callable返回的结果类型必须一致,这是通过泛型来实现的
Callable要采用ExecutorService的submit方法提交,返回为future对象
CompletionService用于提交一组Callable任务,其take方法返回已完成的一个Callable任务对应的Future对象
好比我同时种了几块地的麦子,然后就等待收割,收割时,哪块先成熟,则先收割哪块
下面我们来针对CompletionService看一个小demo
public class CallableAndFuture { /** * @param args */ public static void main(String[] args) { ExecutorService threadPool2 = Executors.newFixedThreadPool(10); CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(threadPool2); for(int i=1;i<=10;i++){ final int seq = i; completionService.submit(new Callable<Integer>() { @Override public Integer call() throws Exception { Thread.sleep(new Random().nextInt(5000)); return seq; } }); } for(int i=0;i<10;i++){ try { System.out.println( completionService.take().get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } } }
执行结果:
8
6
5
7
2
1
3
10
9
4
总结:
对于多线程执行返回结果这种需求在实际应用中还是很少见的,此文只是作为了解学习。
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-09 09:45:21