在Java多线程之中,Callable
和Future
的使用时非常广泛的。在之前的文章中,我们了解了关于Java线程池基础的一些内容,知道如何提交Runnable
的任务。但是,Runnable
的任务是无法有返回值,也不能抛出异常的。而有些时候,我们希望一个线程能够有一些返回值。在Java 5中,引入了java.util.concurrent.Callable
接口,这个接口很类似于Runnable
接口,但是可以返回一个对象,或者抛出异常。
Java Callable
Java的Callable
接口使用了泛型来定义返回的对象的类型。Executors
类提供了一些很实用的方法来在线程池中执行Callable
的任务。因为Callable
的任务通过并行的方式来运行,所以我们需要等待返回的对象。
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
Java Future
Java的Callable
对象返回的就是java.util.concurrent.Future
对象。通过使用Java Future
对象,我们可以知道Callable
任务的执行状态,并且获得返回的对象。Future
接口提供get()
方法来让开发者可以等待Callable
任务的执行,然后获得对应的结果。
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;
}
Java Future提供了一个cancel()
方法来取消关联的Callable
任务的执行。其中的get()
方法是包含一个重载的方法的,我们可以指定等待的时间,而不需要无限期的等待Callable
任务的执行。这个方法可以有效的防止一个线程的无限期的阻塞。
Future
也提供一个isDone()
和一个isCancelled()
方法来找到其关联的Callable
任务的执行状态。
下面是使用Callable
的例子,是在一秒之后返回执行任务的名字。我们通过使用Executor
框架来并行执行100个任务,然后用Future
来获得任务的执行结果。
package com.sapphire.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