Java并发编程(Callable、Future跟CompletionService)
Java并发编程(Callable、Future和CompletionService)
上面这个例子的流程如下
跟线程执行器类似,都是通过submit()方法来提交任务,然后通过take或者poll方法来获取保存任务的对象Future,最后通过Future的get方法来获取对象
上篇博客主要讲解了一下java并发编程中的线程池,这篇呢来谈一下,java并发编程中的任务管理。这篇博客主要涉及到的Future、CompletionService、callable、runnable接口。
runnable接口
可以看看这个接口里面都有哪些操作
<span style="font-size:18px;"><span style="font-size:18px;">public interface Runnable { public abstract void run(); }</span></span>
可以看到其中只有一个public void修饰的run()方法,注意返回值类似是void,调用这个方法是没有返回结果的。但有的时候需要返回结果,因此在java中还为我们提供了Callable这个接口
callable接口
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-family:Comic Sans MS;">public interface Callable<V> { V call() throws Exception; }</span></span></span>
这个方法,在runnable接口有了改进,首先有了返回值,其次有了异常的处理操作。
线程执行器操作Executor
在java中可以,执行器Executor中可以提交两种任务,看下面的方法
<span style="font-size:18px;"><span style="font-size:18px;">public interface ExecutorService extends Executor { void shutdown(); List<Runnable> shutdownNow(); boolean isShutdown(); boolean isTerminated(); boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException; <T> Future<T> submit(Callable<T> task); <T> Future<T> submit(Runnable task, T result); Future<?> submit(Runnable task); } </span></span>
有了上面这个线程池,来执行我们的任务,那么我们如何来获取我们想要达到的结果呢,java中为我们提供了Future接口
<span style="font-size:18px;"><span style="font-size:18px;">public interface Future<V> { boolean cancel(boolean mayInterruptIfRunning); boolean isCancelled(); boolean isDone(); V get() throws InterruptedException, ExecutionException; V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; } </span></span>
这个接口中一共列出来5个方法,其中get()方法用来获取执行的结果,其他几个方法用来判断整个的执行过程
下面来通过一个例子,深入的理解一下上面的几种关系
<span style="font-size:18px;"><span style="font-size:18px;">public static void main(String[] args) { //创建一个线程执行器操作 ExecutorService threadPool = Executors.newSingleThreadExecutor(); //用Future来保存执行的结果 Future<String> future = threadPool.submit( //线程执行器来执行任务 new Callable<String>() { //任务来返回值 public String call() throws Exception { Thread.sleep(2000); return "hello"; }; }); System.out.println("等待结果"); try { try { //想要结果的时候,直接从Future中取出相应的结果就可以了 System.out.println("拿到结果" + future.get(100000, TimeUnit.SECONDS)); } catch (TimeoutException e) { e.printStackTrace(); } } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } };</span></span>
上面这个例子的流程如下
1.创建执行流程器对象:ExecutorService
2.创建任务对象Callable
3.执行流程器执行任务
4.把最终执行的任务结果保存到Futrue中
5.从Futrue中取出任务结果
CompleteService接口
这个接口是为了解决提交一组任务操作,具体方法如下
<span style="font-size:18px;"><span style="font-size:18px;">package java.util.concurrent; public interface CompletionService<V> { Future<V> submit(Callable<V> task); Future<V> submit(Runnable task, V result); Future<V> take() throws InterruptedException; Future<V> poll(); Future<V> poll(long timeout, TimeUnit unit) throws InterruptedException; } </span></span>
跟线程执行器类似,都是通过submit()方法来提交任务,然后通过take或者poll方法来获取保存任务的对象Future,最后通过Future的get方法来获取对象
<span style="font-size:18px;"><span style="font-size:18px;">public void test(){ //创建一个线程执行器对象 ExecutorService threadPool2 = Executors.newSingleThreadExecutor(); //创建执行一组任务的对象操作 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)); // TODO Auto-generated method stub return seq; } }); } for (int i = 0; i < 10; i++) { try { //来获取任务结果 System.out.println(completionService.poll().get()); } catch (Exception e) { } } }</span></span>
版权声明:本文为博主原创文章,未经博主允许不得转载。