Java中除了Runnable接口,还有Callable接口。
两者区别是,后者可以有返回值,一般用于耗时计算。
Runnable接口在线程中用得比较多,一般可以作为线程执行体,Callable一般会与FutureTask结合使用。
Callable接口的源码如下:
/**
* A task that returns a result and may throw an exception.
* Implementors define a single method with no arguments called
* {@code call}.
* 带有返回值的任务,可能抛出异常。
*
* <p>The {@code Callable} interface is similar to {@link
* java.lang.Runnable}, in that both are designed for classes whose
* instances are potentially executed by another thread. A
* {@code Runnable}, however, does not return a result and cannot
* throw a checked exception.
* Callable接口类似于Runnable接口,都是设计用于被其他线程执行的类实例。
* 但是Runnable接口不返回结果,不能抛出一个受检异常。
*
* <p>The {@link Executors} class contains utility methods to
* convert from other common forms to {@code Callable} classes.
* Executors类包含将其他通用形式转成Callable类的辅助类。
*
* @see Executor
* @since 1.5
* @author Doug Lea
* @param <V> the result type of method {@code call}
*/
@FunctionalInterface
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;
}
Future接口用于表示异步计算的结果,该接口包含检查计算是否结束、等待计算结束、获取计算结果的方法。
其中get()可以获取计算结果,在计算完成之前,会一直阻塞当前线程。计算可以被取消。
FutureTask实现了RunnableFuture接口:
public class FutureTask<V> implements RunnableFuture<V> {
而RunnableFuture接口继承自Runnable和Future:
public interface RunnableFuture<V> extends Runnable, Future<V> {
FutureTask表示可取消的异步计算,作为Future接口的实现。FutureTask可以包装Runnable接口,
另外因为实现了Runnable接口,所以可以提交给Executor执行。
下面用代码测试一下:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) throws InterruptedException, ExecutionException {
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("runnable running");
}
};
Callable<Integer> callable = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println("callable running");
return 123;
}
};
Callable<Integer> callable1 = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println("callable1 running");
return 123;
}
};
//runnable
Thread thread1 = new Thread(runnable);
thread1.start();
//callable
FutureTask<Integer> future = new FutureTask<Integer>(callable);
Thread thread2 = new Thread(future);
thread2.start();
System.out.println("future is done? "+future.isDone());
//future.cancel(false);
Thread.sleep(1000);
System.out.println("future result: "+future.get());
ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 0L,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
executor.execute(runnable);
FutureTask<Integer> future1 = new FutureTask<Integer>(callable1);
executor.execute(future1);
FutureTask<String> ft = new FutureTask<String>(runnable, "aaaaa");
Thread thread3 = new Thread(ft);
thread3.start();
while(!ft.isDone()){
Thread.sleep(1000);
}
System.out.println("future runnable result: "+ft.get());
Future<Integer> futureTask = executor.submit(callable);
while(!futureTask.isDone()){
Thread.sleep(1000);
}
System.out.println("futureTask result: "+futureTask.get());
executor.shutdown();
}
}
输出结果:
runnable running
future is done? false
callable running
future result: 123
runnable running
callable1 running
runnable running
future runnable result: aaaaa
callable running
futureTask result: 123