Java Callable Future示例
Java Callable和Future在多线程编程中被大量使用。
在最近的几篇文章中,我们学到了很多有关Java线程的知识,但有时我们希望线程可以返回一些我们可以使用的值。
Java 5在并发包中引入了java.util.concurrent.Callable接口,该接口类似于Runnable接口,但是它可以返回任何Object并能够引发Exception。
Java可调用
Java Callable接口使用Generic定义Object的返回类型。
Executors类提供有用的方法来在线程池中执行Java Callable。
由于可调用任务并行运行,因此我们必须等待返回的Object。
Java Future
Java可调用任务返回java.util.concurrent.Future对象。
使用Java Future对象,我们可以找出Callable任务的状态并获取返回的Object。
它提供了get()方法,可以等待Callable完成,然后返回结果。
Java Future提供了cancel()方法来取消关联的Callable任务。
get()方法有一个重载版本,可以其中指定等待结果的时间,这对于避免当前线程长时间阻塞很有用。
有isDone()和isCancelled()方法来查找关联的Callable任务的当前状态。
这是一个Java Callable任务的简单示例,该示例返回一秒钟后执行该任务的线程的名称。
我们正在使用Executor框架并行执行100个任务,并使用Java Future获取已提交任务的结果。
package com.theitroad.threads; import java.util.ArrayList; import java.util.Date; import java.util.List; 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 MyCallable implements Callable<String> { @Override public String call() throws Exception { Thread.sleep(1000); //return the thread name executing this callable task return Thread.currentThread().getName(); } public static void main(String args[]){ //Get ExecutorService from Executors utility class, thread pool size is 10 ExecutorService executor = Executors.newFixedThreadPool(10); //create a list to hold the Future object associated with Callable List<Future<String>> list = new ArrayList<Future<String>>(); //Create MyCallable instance Callable<String> callable = new MyCallable(); for(int i=0; i< 100; i++){ //submit Callable tasks to be executed by thread pool Future<String> future = executor.submit(callable); //add Future to the list, we can get return value using Future list.add(future); } for(Future<String> fut : list){ try { //print the return value of Future, notice the output delay in console //because Future.get() waits for task to get completed System.out.println(new Date()+ "::"+fut.get()); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } //shut down the executor service now executor.shutdown(); } }
一旦执行完上述程序,您将注意到输出的延迟,因为java Future get()方法等待java可调用任务完成。
另请注意,只有10个线程执行这些任务。
这是上面程序输出的代码片段。
Mon Dec 31 20:40:15 PST 2012::pool-1-thread-1 Mon Dec 31 20:40:16 PST 2012::pool-1-thread-2 Mon Dec 31 20:40:16 PST 2012::pool-1-thread-3 Mon Dec 31 20:40:16 PST 2012::pool-1-thread-4 Mon Dec 31 20:40:16 PST 2012::pool-1-thread-5 Mon Dec 31 20:40:16 PST 2012::pool-1-thread-6 Mon Dec 31 20:40:16 PST 2012::pool-1-thread-7 Mon Dec 31 20:40:16 PST 2012::pool-1-thread-8 Mon Dec 31 20:40:16 PST 2012::pool-1-thread-9 Mon Dec 31 20:40:16 PST 2012::pool-1-thread-10 Mon Dec 31 20:40:16 PST 2012::pool-1-thread-2 ...
提示:如果我们想重写Java Future接口的某些方法,例如,在某个默认时间后而不是无限期地等待,将get()
方法重写为超时,而不是无限期地等待,在这种情况下,Java FutureTask类很方便,它是基本实现未来界面。