Java Callable Example

2025 年 5 月 7 日 | 阅读 4 分钟

Java 提供了两种创建线程的方法:一种是通过实现 Runnable 接口,另一种是通过继承 Thread 类。然而,在实现 Runnable 接口时,有一个重要的功能缺失,那就是线程在完成执行后(即 run() 方法执行完毕后)无法返回任何结果。为了支持这一功能,就使用了Java Callable 接口

要理解 Callable 的概念,必须熟悉线程和多线程的概念。

call() 方法签名

Callable 示例

让我们来观察一下实现 Callable 接口的代码片段,该代码将在 0 到 4 秒的延迟后返回一个 0 到 9 之间的随机数。

文件名: JavaCallableExample.java

解释: 上面的代码片段展示了如何实现 callable 接口。然而,工作并未完成。当 call() 方法终止时,返回的对象必须被存储,以便主线程能够获取到。这很重要,因为主线程必须知道 call() 方法生成的结果。为了实现这一点,我们使用了 Future 对象。Future 对象保存了从不同线程获取的结果,这些结果是从 call() 方法发送过来的。

Callable 类似,Future 也是一个接口。因此,为了使用它,必须实现它。然而,我们不必费力去实现 Future 接口。Java 库中已经有了一个名为 FutureTask 的类,它同时实现了 Runnable 和 Future 接口。

现在,让我们扩展上面的代码片段。

文件名: JavaCallableExample.java

输出

The random number is: 5
The random number is: 0
The random number is: 1
The random number is: 3
The random number is: 9
The random number is: 0
The random number is: 7
The random number is: 9
The random number is: 3
The random number is: 5

解释: 在代码中,我们创建了 10 个不同的线程。每个线程都调用 call() 方法,生成一个随机数并返回。get() 方法用于将不同线程返回的随机数对象接收到主线程。get() 方法在 Future 接口中声明,并在 FutureTask 类中实现。

Callable 和 Runnable 接口的区别

下表显示了 Callable 和 Runnable 接口之间的区别。

CallableRunnable
如果我们要处理 Callable 接口,则必须定义 call() 方法。如果我们要处理 Runnable 接口,则必须定义 run() 方法。
接口的 call() 方法的返回类型是 Object。因此,call() 方法返回一个 Object。接口的 run() 方法的返回类型是 void。因此,run() 方法返回 void。
call() 方法可以抛出异常。run() 方法不能抛出异常。
不能使用 Callable 接口创建线程。可以使用 Runnable 接口创建线程。