java Callable 应该比 Runnable 更受欢迎吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16757142/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Shall Callable be preferred over Runnable?
提问by sheidaei
I have understood the difference between Runnable
and Callable
interface in Java. From Java 1.5 additional features has been added to Runnable
interface and has been called Callable
in order to maintain backward compatibility.
我已经了解Java 中Runnable
和Callable
接口之间的区别。从 Java 1.5 开始,附加功能已添加到Runnable
界面中,并已被调用Callable
以保持向后兼容性。
My questions is now that we have Callable
interface, shall we always use that? What are the use cases of not using Callable
and using Runnable
?
我的问题是现在我们有了Callable
界面,我们应该一直使用它吗?不使用Callable
和使用的用例是Runnable
什么?
(Thisis a good article on what are the differences between them)
(这是一篇关于它们之间有什么区别的好文章)
采纳答案by barfuin
Both have their uses, and both are supported by the Executor framework in java.util.concurrent. Runnable has been around longer, but it is still in use and not discouraged.
两者都有它们的用途,并且都由 java.util.concurrent 中的 Executor 框架支持。Runnable 已经存在的时间更长了,但它仍在使用中,并不气馁。
Callables can throw exceptions and return values, which makes them the better abstraction for result-bearing tasks (such as fetching a resource from the network, performing an expensive computation of a value, and the like) [from Java Concurrency in Practiceby Goetz, Bloch et. al., the standard work on Java concurrency].
Callables 可以抛出异常并返回值,这使得它们成为结果承载任务的更好抽象(例如从网络获取资源,执行昂贵的值计算等)[来自Goetz 的Java Concurrency in Practice,布洛赫等。al.,Java 并发的标准工作]。
So, if you are designing an API, I would suggest using Callables when possible. If you are sure that the tasks will not return values and will not throw exceptions, then Runnables are also a valid choice. There is no black and white here, especially because Runnables can easily be wrapped in Callables and vice versa.
因此,如果您正在设计 API,我建议您尽可能使用 Callables。如果您确定任务不会返回值并且不会抛出异常,那么 Runnables 也是一个有效的选择。这里没有非黑即白,特别是因为 Runnables 可以很容易地包装在 Callables 中,反之亦然。
As an aside, note that your Callable implementation need not declare throws Exception
; the fact that Callable itself declares it is only to allow implementors to throw any checked exceptions. Callers of your Callable who rely solely on the Callable interface will have to write exception handling code, though.
Also note that Callables need not return a value; you can simply declare your Callable to return Void
(with capital 'V
').
顺便说一句,请注意您的 Callable 实现不需要声明throws Exception
; Callable 本身声明它只是为了允许实现者抛出任何已检查的异常的事实。但是,仅依赖 Callable 接口的 Callable 的调用者将不得不编写异常处理代码。
另请注意,Callables 不需要返回值;您可以简单地声明您的 Callable 返回Void
(使用大写“ V
”)。
回答by JB Nizet
IMHO, Runnable is a better type to use when taking as argument a function which
恕我直言,Runnable 是一种更好的类型,当将一个函数作为参数时使用
- doesn't have a returned value, but only side effects
- must handle exceptions, and not propagate them
- 没有返回值,只有副作用
- 必须处理异常,而不是传播它们
Don't forget that Callable.call()
throws Exception. That means that if you take a Callable as argument, this Callable can throw any kind of exception, and you must have a way to handle them all in a correct way. If you can't do that, it's better to let the implementor of the Callable handle the exception as he wants to, and make the argument a Runnable to make that clear.
不要忘记Callable.call()
抛出异常。这意味着如果你将一个 Callable 作为参数,这个 Callable 可以抛出任何类型的异常,你必须有一种方法以正确的方式处理它们。如果你不能这样做,最好让 Callable 的实现者按照他的意愿处理异常,并将参数设为 Runnable 以明确这一点。
回答by Evgeniy Dorofeev
Use case of not using Callable
: ScheduledExecutorService.scheduleAtFixedRate
and scheduleWithFixedDelay
accepts only Runnable
.
使用不使用的情况下Callable
:ScheduledExecutorService.scheduleAtFixedRate
与scheduleWithFixedDelay
仅接受Runnable
。
回答by Steve K
I prefer Callable
s, but in those rare instances you might need a Callable
to be Runnable
, you can easily implement both by adding a run()
method like this to your Callable
.
我更喜欢Callable
s,但在那些极少数情况下,您可能需要 aCallable
成为Runnable
,您可以通过将这样的run()
方法添加到您的Callable
.
public void run(){
try{
call();
} catch (Exception e){
e.printStackTrace(); // or however you log errors
}
}
In Java 8, you can also make an interface to do the same thing for you:
在 Java 8 中,你还可以创建一个接口来为你做同样的事情:
public interface CallableRunnable<T> extends Callable<T>, Runnable {
default void run(){
try {
call();
} catch (Exception e) {
e.printStackTrace(); // or however you log errors
}
}
}
Then you just have to change anything that implements Callable<T>
to implements CallableRunnable<T>
.That way, your jobs can always be called by any method that requires either. Of course, if you need specific error handling, you can still override the run() method to handle the exceptions thrown by your call()
method. You could even implement a method to do so:
然后,您只需将任何内容更改implements Callable<T>
为implements CallableRunnable<T>
。这样,您的作业始终可以由任何需要的方法调用。当然,如果您需要特定的错误处理,您仍然可以覆盖 run() 方法来处理您的call()
方法抛出的异常。你甚至可以实现一个方法来做到这一点:
public interface CallableRunnable<T> extends Callable<T>, Runnable {
default void run(){
try {
call();
} catch (Exception e) {
handleCallExceptions(e);
}
}
default void handleCallExceptions(Exception e){
e.printStackTrace();
}
}
Then any special exception handling only needs to implement its own handleExceptions(Exception)
method... but you don't have to if you don't need to. I prefer this because it allows you to have an implementation that uses your logging framework, etc.
那么任何特殊的异常处理只需要实现它自己的handleExceptions(Exception)
方法......但如果你不需要,你就不必。我更喜欢这个,因为它允许你有一个使用你的日志框架等的实现。
回答by Sudhakar Pandey
Callable and Runnableboth is similar to each other and can use in implementing thread. In case of implementing Runnableyou must implement run()method but in case of callable you must need to implement call()method, both method works in similar ways but callable call()method have more flexibility.There is some differences between them.
Callable 和Runnable两者相似,都可以用于实现线程。在实现Runnable 的情况下,你必须实现run()方法,但在可调用的情况下,你必须实现call()方法,这两种方法的工作方式相似,但可调用的call()方法具有更大的灵活性。它们之间存在一些差异。
Difference between Runnableand callableas below--
Runnable和callable之间的区别如下-
1) The run()method of runnablereturns void, means if you want your thread return something which you can use further then you have no choice with Runnable run()method. There is a solution 'Callable', If you want to return any thing in form of objectthen you should use Callable instead of Runnable. Callable interface have method 'call()' which returns Object.
1) runnable的run()方法返回void,这意味着如果您希望您的线程返回一些您可以进一步使用的东西,那么您别无选择 Runnable run()方法。有一个解决方案'Callable',如果你想以对象的形式返回任何东西,那么你应该使用 Callable 而不是 Runnable。可调用接口具有返回 Object 的方法“call()”。
Method signature - Runnable->
方法签名 - Runnable->
public void run(){}
Callable->
可调用->
public Object call(){}
2) In case of Runnable run()method if any checked exception arises then you must need to handled with try catch block, but in case of Callable call()method you can throw checked exceptionas below
2) 在Runnable run()方法的情况下,如果出现任何检查异常,那么您必须使用 try catch 块处理,但在Callable call()方法的情况下,您可以抛出检查异常,如下所示
public Object call() throws Exception {}
3) Runnablecomes from legacy java 1.0version, but callablecame in Java 1.5version with Executerframework.
3) Runnable来自遗留的java 1.0版本,但callable来自带有Executer框架的Java 1.5版本。
If you are familiar with Executersthen you should use Callable instead of Runnable.
如果您熟悉Executers,那么您应该使用 Callable 而不是 Runnable。
Hope you understand.
希望你能理解。