本文是Sun官方以Blog形式发布的Java核心技术窍门(JavaCoreTechTip)中的一个。本文主要介绍了Callable及其相关接口和类的使用,篇幅不长且易于理解,故翻译在了此处,相信对于准备或刚接触java.util.concurrent的朋友会有所帮助。
自从Java平台的最开始,Runnable接口就已存在了。它允许你定义一个可由线程完成的任务。如大多数人所已知的那样,它只提供了一个run方法,该方法既不接受任何参数,也不返回任何值。如果你需要从一个未完成的任务中返回一个值,你就必须在该接口之外使用一个方法去等待该任务完成时通报的某种消息。例如,下面的示例就是你在这种情景下可能做的事情:
Runnable runnable = ...;
Thread t = new Thread(runnable);
t.start();
t.join();
String value = someMethodtoGetSavedValue()
严格来说,上述代码并无错误,但现在可用不同的方法去做,这要感谢J2SE 5.0引入的Callable接口。不同于Runnable接口拥有run方法,Callable接口提供的是call方法,该方法可以返回一个Object对象,或可返回任何一个在泛型化格式中定义了的特定类型的对象。
public interface Callable<V> {
V call() throws Exception;
}
因为你不可能把Callable对象传到Thread对象去执行,你可换用ExecutorService对象去执行Callable对象。该服务接受Callable对象,并经由submit方法去执行它。
<T> Future<T> submit(Callable<T> task)
如该方法的定义所示,提交一个Callable对象给ExecutorService会返回一个Future对象。然后,Future的get方法将会阻塞,直到任务完成。
为了证明这一点,下面的例子为命令行中的每个词都创建一个单独的Callable实例,然后把这些词的长度加起来。各个Callable对象将只是计算它自己的词的长度之和。Futures对象的Set集合将被保存以便从中获得计算用的值。如果需要保持返回值的顺序,则可换用一个List对象。
import java.util.*; import java.util.concurrent.*;
public class CallableExample {
public static class WordLengthCallable implements Callable { private String word; public WordLengthCallable(String word) { this.word = word; } public Integer call() { return Integer.valueOf(word.length()); } }
public static void main(String args[]) throws Exception { ExecutorService pool = Executors.newFixedThreadPool(3); Set<Future<Integer>> set = new HashSet<Future≶Integer>>(); for (String word: args) { Callable<Integer> callable = new WordLengthCallable(word); Future<Integer> future = pool.submit(callable); set.add(future); } int sum = 0; for (Future<Integer> future : set) { sum += future.get(); } system.out.printf("The sum of lengths is %s%n", sum); system.exit(sum); } }
|
WordLengthCallable保存了每个词并使用该词的长度作为call方法的返回值。这个值可能会花点儿时间去生成,不过在这个例子中,可以立即知道它。 call方法的唯一要求是这个值要在call方法的结尾处返回。当Future的get方法稍后被调用时,如果任务运行得很快的话,Future将会自动得到这个值(如同本例的情况),否则将一直等到该值生成完毕为止。多次调用get方法不会导致任务从该线程返回。因为该程序的目的是计划所有字的长度之和,它不会强令Callable任务结束。如果最后一个任务在前三个任务之前完成,也是没错的。对Future的get方法的第一次调用将只会等待Set中第一个任务结束,而不会阻塞其它的任务分别执行完毕。它只会等待当次线程或任务结束。这个特定的例子使用固定数线程池来产生ExecutorService对象,但其它有效的方法也是可行的。
关于执行器和线程池用法的更多信息,请见Java Tutorial中Executors一节。SwingWorker类是另一个使用Future的Runnable对象的例子,尽管有些微不同之处。更多信息请见Java Tutorial中Worker Threads and SwingWorker一节。
分享到:
相关推荐
"Java使用Callable和Future创建线程操作示例" Java使用Callable和Future创建线程操作示例主要介绍了Java使用Callable和Future创建线程操作,结合实例形式分析了java使用Callable接口和Future类创建线程的相关操作...
在Java编程语言中,Callable接口是用于创建能够返回结果并可能抛出异常的线程的。与Runnable接口相比,Callable接口提供了更强大的功能,因为Runnable只能定义无返回值的任务,而Callable可以定义有返回值的任务。这...
2. `Callable`: `Callable`接口比`Runnable`更强大,因为它允许返回一个结果。你需要实现`call()`方法,其中可以包含计算逻辑并返回一个值。但直接创建`Callable`线程并不容易,因为`Thread`不接受`Callable`对象,...
在实际开发中,ExecutorService(如ThreadPoolExecutor)经常与Future和FutureTask一起使用,因为ExecutorService可以提交Runnable或Callable任务,并返回Future,从而实现对任务的异步处理和结果获取。例如: ```...
3. **结果的获取**:由于`Callable`任务可以返回结果,因此执行`Callable`任务后会返回一个`Future`对象,这个对象提供了对异步计算的结果的访问。通过调用`Future`对象的`get()`方法,可以阻塞等待任务完成并获取...
或者使用Callable创建一个可以返回结果的线程: ```java Future<Integer> future = executorService.submit(new Callable() { @Override public Integer call() throws Exception { return someComputation(); ...
例如,可以使用`Executors.callable(Runnable task, V result)`将一个Runnable转换为Callable,这样Runnable的任务就可以返回一个结果。 7. **应用场景** Callable常用于FutureTask或者ExecutorService中。...
Callable 与 Runnable 相似,但具有更强大的功能,允许任务返回结果并处理异常。 Callable 接口: Callable 接口中定义了 `call()` 方法,与 Runnable 的 `run()` 方法不同。`call()` 方法可以抛出受检异常...
`submit`方法不仅将任务提交到线程池执行,还会返回一个`Future`对象,我们可以使用这些`Future`对象来获取异步计算的结果。 `Future`接口提供了获取任务结果的方法`get()`,这个方法会阻塞直到任务完成并返回结果...
2. `Runnable`或`Callable`: 这些是任务的实现,`Runnable`不返回结果,而`Callable`可以返回一个`Future`对象,包含任务的执行结果。 3. `submit()`方法:用于向`ExecutorService`提交任务,如果任务是`Callable`...
在Java SE5中引入的Callable是一种具有类型参数的泛型,它的类型参数表示的是从方法call()中返回的值,并且必须使用ExecutorService.submit()方法调用它。 import java.util.ArrayList; import java.util....
Callable接口和Future接口的组合使用,能够实现多线程并发执行任务,并获取执行结果。 一、Callable接口简介 Callable接口是一个泛型接口,用于表示可以调用并返回结果的代码。它提供了一个call()方法,该方法...
Callable接口可以获取到线程的返回结果,而Future接口可以通过get方法来承接线程执行的结果。下面我们通过一个示例代码来演示Callable和Future的使用: 首先,我们需要创建一个ThreadPoolExecutor来管理线程池。...
相比Runnable,Callable使得并行任务能返回计算结果,这对于需要处理计算结果的场景非常有用。 Future接口则用于管理Callable任务的执行状态和结果。它提供了检查任务是否完成、取消任务、获取任务结果等方法。以下...
一直以来感觉使用Mybatis查询存储过程...写了一个拦截器,可以把储存过程的输出参数当做返回值来返回。其实也简单不了多少,只不过在设计Dao接口的时候能更统一吧。 使用方式可以看一下这里 标签:Mybatis
Callable 接口是一个函数式接口,定义了一个抽象方法 `call()`,该方法返回一个结果对象。Callable 接口通常用于执行异步任务,并且可以获取任务的执行结果。 Callable 接口的实现 在上面的代码中,定义了一个实现...
因为`$f`是一个可调用的闭包,所以这段代码能够正确执行并返回预期的结果。 总结起来,为了提高代码的稳定性和可维护性,我们应该在定义接受回调参数的函数时使用`callable`类型约束。这不仅可以避免在运行时因回调...
例如,在执行一些长时间的计算任务时,可以使用Callable接口来获取计算结果。 Callable接口的实现 要实现Callable接口,需要重写call()方法,该方法返回一个值。例如: ```java import java.util.concurrent....
但是,Runnable接口的run()方法无返回值,而Callable的call()方法可以返回一个结果,并且允许在计算过程中抛出异常。在上述示例中,`MyThread`类实现了Callable接口,其call()方法会打印"call",休眠5秒,然后返回...
在JavaSE5中引入的Callable是一个具有类型参数的范型,他的类型参数方法表示为方法call()而不是run()中返回的值,并且必须使用ExecutorService.submint()方法进行调用。 Callable接口规定的方法是call(),而...