Runnable 自 Java 1.0 时就有了,而 Callable 接口在 Java 1.5 时才被加入。两者都是 Functional 接口,也就是说可以直接使用 Lambda 表达式来实现线程函数,不一定非得实现一个类来实现接口。Runnable 可以直接传给 Thread 构造方法,Callable 不可以。 Callable 只能使用 ExecutorService,但是 Callable 可以返回线程的运行结果,Runnable 不可以,如果使用 Lambda 表达式来获得线程函数的运行结果,则需要一点小技巧。
下面是示例代码和它的运行结果。这段程序使用一个单独的线程来计算阶乘,然后输出结果。可以看到,使用 Callable 可以直接通过 future.get().intValue 得到结果,而 Runnable 中我们先声明了一个 Lambda 外的本地变量,然后在 Lambda 表达式中赋值得到的结果。这个本地变量的类型很特殊,这是因为 Java 对在 Lambda 里改变本地变量的限制造成的。
Callable 的 future 结果还可以通过 getCause 来得到线程函数中的异常,虽然两者都可以通过 ExecutionException 捕捉到运行异常。
public class Main {
public static void main(String[] args) {
factorialWithRunnable(3);
factorialWithCallable(3);
factorialWithRunnable(-1);
factorialWithCallable(-1);
}
static void factorialWithRunnable(int n) {
System.out.println("--- factorialWithRunnable ---");
final Integer[] result = new Integer[1];
Runnable task = () -> {
result[0] = factorial(n);
};
ExecutorService executorService = Executors.newSingleThreadExecutor();
var future = executorService.submit(task);
try {
future.get();
System.out.println(MessageFormat.format("factorialWithRunnable result: {0}", result[0]));
} catch (ExecutionException e) {
System.out.println(e.getMessage());
} catch (InterruptedException interruptedException) {
System.out.println(interruptedException.getMessage());
}
executorService.shutdown();
}
static void factorialWithCallable(int n) {
System.out.println("--- factorialWithCallable ---");
Callable<Integer> task = () -> {
return factorial(n);
};
ExecutorService executorService = Executors.newSingleThreadExecutor();
var future = executorService.submit(task);
try {
var result = future.get().intValue();
System.out.println(MessageFormat.format("factorialWithCallable result: {0}", result));
} catch (ExecutionException e) {
System.out.println(e.getMessage());
} catch (InterruptedException interruptedException) {
System.out.println(interruptedException.getMessage());
}
executorService.shutdown();
}
static int factorial(int n)
{
if (n <= 0) {
throw new IllegalArgumentException("Argument cannot be negative!");
}
int r = 1;
for (int i = 1; i <= n; i++) {
r *= i;
}
return r;
}
}
以下是执行结果: