java 中的 Callable 与 Supplier 接口
Callable vs Supplier interface in java
Callable
和Supplier
包中的java.util.concurrent
和java.util.function
函数接口分别有如下签名-
public interface Callable<V> {
V call() throws Exception;
}
public interface Supplier<T> {
T get();
}
是否有一些特定的用例,其中每一个都比另一个更适合?
它们在用法上的区别可以从各自的文档中看出:
A task that returns a result and may throw an exception. Implementors
define a single method with no arguments called call.
The Callable interface is similar to Runnable, in that both are
designed for classes whose instances are potentially executed by
another thread.
Represents a supplier of results.
There is no requirement that a new or distinct result be returned each
time the supplier is invoked.
这意味着 Callable.call
的调用者期望抛出异常并将相应地处理异常。这对于读取和写入文件等任务很有用,在这些任务中可以抛出多种 IOException
。 Callable
也被设计为 运行 在另一个线程上。
Supplier
另一方面,非常一般。只是 "supplies a value" 而已。
所以 Callable
比 Supplier
更专业。如果您不处理另一个线程或者您的任务不太可能抛出异常,建议使用 Supplier
。
除了显而易见的 Callable 抛出异常之外,区别在于语义。它们有不同的名称,因为它们代表不同的事物。目的是让代码更容易理解。当您使用 Callable 时,您的接口选择意味着该对象将由另一个线程执行。当您使用 Supplier 时,您暗示它只是一个向另一个组件提供数据的对象。
来龙去脉
对于 Runnable
和 Callable
,它们自 Java 6 以来一直是并发包的一部分。这意味着它们都已准备好提交给 Executor
和 运行 异步。这里Callable
有具体的用法
而对于 Runnable
(0 进 0 出)、Supplier
(0 进 1 出)、Consumer
(1 进 0 出)和 Function
(1 in 1 out),自 Java 8 以来,它们一直是功能特性的一部分。所有这些都准备好由 lambda 友好的东西处理,比如 CompletableFuture
。这里 Supplier
只是表示一个没有任何输入参数但有一个 return 值的函数,这是高度抽象的。
IMO,Callable 和 Supplier 之间的主要区别在于您更喜欢使用已检查异常还是未检查异常。
早些时候,Java 生态系统习惯于为每个预计会遇到的场景选择检查异常。但是 post java-8,checked exceptions 已经不再流行了。 (例如:ExecutionException 与 CompletionException 通常都用于在执行异步任务期间包装异常,但前者被检查而后者未被检查)
这甚至在某些库中也能看到(Jacksons json 解析抛出已检查的异常与 Gson 抛出未经检查的异常等)。
说如果要在另一个线程中执行,就用Callable是不对的。例如,CompletableFuture.supplyAsync(supplier)
在另一个线程中执行供应商。
Callable
和Supplier
包中的java.util.concurrent
和java.util.function
函数接口分别有如下签名-
public interface Callable<V> {
V call() throws Exception;
}
public interface Supplier<T> {
T get();
}
是否有一些特定的用例,其中每一个都比另一个更适合?
它们在用法上的区别可以从各自的文档中看出:
A task that returns a result and may throw an exception. Implementors define a single method with no arguments called call.
The Callable interface is similar to Runnable, in that both are designed for classes whose instances are potentially executed by another thread.
Represents a supplier of results.
There is no requirement that a new or distinct result be returned each time the supplier is invoked.
这意味着 Callable.call
的调用者期望抛出异常并将相应地处理异常。这对于读取和写入文件等任务很有用,在这些任务中可以抛出多种 IOException
。 Callable
也被设计为 运行 在另一个线程上。
Supplier
另一方面,非常一般。只是 "supplies a value" 而已。
所以 Callable
比 Supplier
更专业。如果您不处理另一个线程或者您的任务不太可能抛出异常,建议使用 Supplier
。
除了显而易见的 Callable 抛出异常之外,区别在于语义。它们有不同的名称,因为它们代表不同的事物。目的是让代码更容易理解。当您使用 Callable 时,您的接口选择意味着该对象将由另一个线程执行。当您使用 Supplier 时,您暗示它只是一个向另一个组件提供数据的对象。
来龙去脉
对于 Runnable
和 Callable
,它们自 Java 6 以来一直是并发包的一部分。这意味着它们都已准备好提交给 Executor
和 运行 异步。这里Callable
有具体的用法
而对于 Runnable
(0 进 0 出)、Supplier
(0 进 1 出)、Consumer
(1 进 0 出)和 Function
(1 in 1 out),自 Java 8 以来,它们一直是功能特性的一部分。所有这些都准备好由 lambda 友好的东西处理,比如 CompletableFuture
。这里 Supplier
只是表示一个没有任何输入参数但有一个 return 值的函数,这是高度抽象的。
IMO,Callable 和 Supplier 之间的主要区别在于您更喜欢使用已检查异常还是未检查异常。
早些时候,Java 生态系统习惯于为每个预计会遇到的场景选择检查异常。但是 post java-8,checked exceptions 已经不再流行了。 (例如:ExecutionException 与 CompletionException 通常都用于在执行异步任务期间包装异常,但前者被检查而后者未被检查)
这甚至在某些库中也能看到(Jacksons json 解析抛出已检查的异常与 Gson 抛出未经检查的异常等)。
说如果要在另一个线程中执行,就用Callable是不对的。例如,CompletableFuture.supplyAsync(supplier)
在另一个线程中执行供应商。