Java中可运行接口和可调用接口的区别

Java中可运行接口和可调用接口的区别,java,multithreading,interface,runnable,callable,Java,Multithreading,Interface,Runnable,Callable,在Java中设计并发线程时,使用Runnable接口和Callable接口有什么区别,为什么要选择其中一个呢?请参见说明 可调用接口类似于 Runnable,因为两者都是经过设计的 对于实例为 可能由另一方执行 线但是,Runnable不能 返回一个结果,但不能抛出 检查异常。 我在另一个博客中发现了这一点,可以对其进行更多的解释: 虽然这两个接口都是由希望在不同的执行线程中执行的类实现的,但这两个接口之间几乎没有什么区别: Callable实例返回类型为V的结果,而Runnable实例不返回

在Java中设计并发线程时,使用
Runnable
接口和
Callable
接口有什么区别,为什么要选择其中一个呢?

请参见说明

可调用接口类似于 Runnable,因为两者都是经过设计的 对于实例为 可能由另一方执行 线但是,Runnable不能 返回一个结果,但不能抛出 检查异常。


我在另一个博客中发现了这一点,可以对其进行更多的解释:

虽然这两个接口都是由希望在不同的执行线程中执行的类实现的,但这两个接口之间几乎没有什么区别:

  • Callable
    实例返回类型为
    V
    的结果,而
    Runnable
    实例不返回
  • Callable
    实例可能抛出选中的异常,而
    Runnable
    实例则不能
Java的设计者感到有必要扩展
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);
    }