Java中可运行接口和可调用接口的区别
在Java中设计并发线程时,使用Java中可运行接口和可调用接口的区别,java,multithreading,interface,runnable,callable,Java,Multithreading,Interface,Runnable,Callable,在Java中设计并发线程时,使用Runnable接口和Callable接口有什么区别,为什么要选择其中一个呢?请参见说明 可调用接口类似于 Runnable,因为两者都是经过设计的 对于实例为 可能由另一方执行 线但是,Runnable不能 返回一个结果,但不能抛出 检查异常。 我在另一个博客中发现了这一点,可以对其进行更多的解释: 虽然这两个接口都是由希望在不同的执行线程中执行的类实现的,但这两个接口之间几乎没有什么区别: Callable实例返回类型为V的结果,而Runnable实例不返回
Runnable
接口和Callable
接口有什么区别,为什么要选择其中一个呢?请参见说明
可调用接口类似于
Runnable,因为两者都是经过设计的
对于实例为
可能由另一方执行
线但是,Runnable不能
返回一个结果,但不能抛出
检查异常。
我在另一个博客中发现了这一点,可以对其进行更多的解释: 虽然这两个接口都是由希望在不同的执行线程中执行的类实现的,但这两个接口之间几乎没有什么区别:
实例返回类型为Callable
的结果,而V
实例不返回Runnable
实例可能抛出选中的异常,而Callable
实例则不能Runnable
Runnable
接口的功能,但是他们不想影响Runnable
接口的使用,这可能是他们在Java1.5中使用名为Callable
的单独接口的原因,而不是更改现有的Runnable
Runnable
和Callable
的应用程序有什么区别。差异是否仅存在于可调用的中的返回参数
基本上,是的。请参阅的答案。还有
如果Callable
可以完成Runnable
所能做的一切,那么有什么必要同时拥有这两者呢
因为Runnable
接口不能做Callable
所做的一切
Runnable
从Java1.0开始就存在,但是Callable
仅在Java1.5中引入。。。处理Runnable
不支持的用例。理论上,Java团队本可以更改Runnable.run()
方法的签名,但这会破坏与1.5之前版本代码的二进制兼容性,在将旧Java代码迁移到新JVM时需要重新编码。这是一个巨大的禁忌。Java努力做到向后兼容。。。这是Java在商业计算方面最大的卖点之一
显然,在某些用例中,任务不需要返回结果或抛出已检查异常。对于这些用例,使用Runnable
比使用Callable
并从call()
方法返回一个伪(null
)值更简洁。正如前面提到的,Callable是一个相对较新的接口,它是作为并发包的一部分引入的。Callable和Runnable都可以与执行器一起使用。类线程(实现Runnable本身)只支持Runnable
您仍然可以对执行器使用Runnable。Callable的优点是,您可以将其发送给executor,并立即返回将来的结果,该结果将在执行完成时更新。Runnable也可以实现这一点,但在这种情况下,您必须自己管理结果。例如,您可以创建包含所有结果的结果队列。其他线程可以在此队列上等待并处理到达的结果。
Callable
需要实现call()
方法,而Runnable
需要实现run()
方法
Callable
可以返回值,但Runnable
不能
Callable
可以抛出checked异常,但Runnable
不能
Callable
可以与ExecutorService#invokeXXX(Collection让我们看看在哪里可以使用Runnable和Callable
Runnable和Callable都运行在与调用线程不同的线程上。但是Callable可以返回值,而Runnable不能。那么这在哪里真正适用呢
Runnable:如果您有一个fire-and-forget任务,那么使用Runnable。将代码放在Runnable中,当调用run()方法时,您可以执行任务。调用线程实际上并不关心您何时执行任务
Callable:如果您试图从任务中检索值,请使用Callable。现在Callable本身无法完成此任务。您将需要一个围绕Callable的未来,并在Future.get()上获取值。在这里,调用线程将被阻塞,直到将来返回结果,而结果将等待Callable的call()方法执行
因此,请考虑一个目标类的接口,其中定义了可运行和可调用的包装方法。调用类将随机调用接口方法,而不知道哪些是可运行的,哪些是可调用的。可运行方法将异步执行,直到调用可调用方法为止。调用类的线程将阻止,因为您正在从目标类检索值
注意:在您的目标类中,您可以在单个线程执行器上调用Callable和Runnable,使此机制类似于串行调度队列。因此,只要调用方调用您的Runnable包装方法,调用线程就会在不阻塞的情况下快速执行。只要调用Callable包装的Future方法,调用线程就会立即执行它必须阻塞,直到所有其他排队的项都被执行。只有这样,该方法才会返回值。这是一种同步机制。Callable
接口声明call()
方法,并且您需要提供泛型作为对象调用()的类型返回-
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
总而言之,很少有显著差异
Runnable
对象不返回结果,而对象
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
<T> Future<T> submit(Callable<T> task);
Future<?> submit(Runnable task);
<T> Future<T> submit(Runnable task, T result);
public class HelloRunnable implements Runnable {
public void run() {
System.out.println("Hello from a thread!");
}
public static void main(String args[]) {
(new Thread(new HelloRunnable())).start();
}
}
+----------------------------------------+--------------------------------------------------------------------------------------------------+
| Runnable | Callable<T> |
+----------------------------------------+--------------------------------------------------------------------------------------------------+
| Introduced in Java 1.0 of java.lang | Introduced in Java 1.5 of java.util.concurrent library |
| Runnable cannot be parametrized | Callable is a parametrized type whose type parameter indicates the return type of its run method |
| Runnable has run() method | Callable has call() method |
| Runnable.run() returns void | Callable.call() returns a generic value V |
| No way to propagate checked exceptions | Callable's call()“throws Exception” clause so we can easily propagate checked exceptions further | |
+----------------------------------------+--------------------------------------------------------------------------------------------------+
public void run(){}
public Object call(){}
public Object call() throws Exception {}
//Runnable
interface Runnable {
void run();
}
//Action - throws exception
interface Action {
void run() throws Exception;
}
//Consumer - consumes a value/values, throws exception
interface Consumer1<T> {
void accept(T t) throws Exception;
}
//Callable - return result, throws exception
interface Callable<R> {
R call() throws Exception;
}
//Supplier - returns result, throws exception
interface Supplier<R> {
R get() throws Exception;
}
//Predicate - consumes a value/values, returns true or false, throws exception
interface Predicate1<T> {
boolean test(T t) throws Exception;
}
//Function - consumes a value/values, returns result, throws exception
public interface Function1<T, R> {
R apply(T t) throws Exception;
}
...
//Executor
public interface Executor {
void execute(Runnable command);
}