[java] Java에서 Runnable 인터페이스와 Callable 인터페이스의 차이점

Java에서 동시 스레드를 디자인 할 때 인터페이스 RunnableCallable인터페이스 를 사용하는 것의 차이점은 무엇입니까 ?



답변

여기 설명을 참조 하십시오 .

Callable 인터페이스는 Runnable과 유사합니다. 둘 다 인스턴스가 다른 스레드에 의해 잠재적으로 실행될 수있는 클래스를 위해 설계되었습니다. 그러나 Runnable은 결과를 반환하지 않으며 확인 된 예외를 throw 할 수 없습니다.


답변

어떤이의 애플리케이션에서 차이가있다 RunnableCallable. 에 반환 매개 변수와의 차이점 만 Callable있습니까?

기본적으로 그렇습니다. 이 질문에 대한 답변을 참조하십시오 . 에 대한 javadocCallable .

Callable모든 것을 할 수 있다면 둘 다 가질 필요는 무엇입니까 Runnable?

Runnable인터페이스 가 모든 것을 할 수 없기 때문에 Callable!

RunnableJava 1.0 이후로 사용되었지만 CallableJava 1.5에서만 소개되었습니다 … Runnable지원하지 않는 사용 사례를 처리하기 위해. 이론적으로 Java 팀은 Runnable.run()메소드 의 서명을 변경했을 수 있지만 이는 1.5 이전 코드와 바이너리 호환성을 손상시켜 이전 Java 코드를 최신 JVM으로 마이그레이션 할 때 코드를 다시 작성해야합니다. 그것은 큰 NO-NO입니다. Java는 이전 버전과의 호환성을 위해 노력하고 있으며 이는 비즈니스 컴퓨팅을위한 Java의 가장 큰 판매 지점 중 하나입니다.

그리고 분명히 작업이 결과를 반환하거나 확인 된 예외를 throw 할 필요 가없는 사용 사례가 있습니다 . 이러한 유스 케이스의 경우 사용 Runnable은 메소드 에서 Callable<Void>더미 ( null) 값을 사용 하고 리턴하는 것보다 더 간결 합니다 call().


답변

  • A는 Callable구현해야 call()잠시 방법을 Runnable요구 구현하는 run()방법을.
  • A Callable는 값을 반환 할 수 있지만 a는 반환 Runnable할 수 없습니다.
  • A Callable는 검사 예외를 던질 수 있지만 Runnable불가능합니다.
  • A CallableExecutorService#invokeXXX(Collection<? extends Callable<T>> tasks)메소드 와 함께 사용할 수 있지만 a Runnable는 사용할 수 없습니다.

    public interface Runnable {
        void run();
    }
    
    public interface Callable<V> {
        V call() throws Exception;
    }

답변

나는 이것을 다른 블로그 에서이 차이점을 조금 더 설명 할 수있는 것을 발견했다 .

두 인터페이스는 다른 실행 스레드에서 실행하려는 클래스에 의해 구현되지만 두 인터페이스 사이에는 다음과 같은 차이점이 거의 없습니다.

  • Callable<V>인스턴스 유형의 결과를 반환 V반면, Runnable인스턴스하지 않습니다.
  • Callable<V>인스턴스는 반면, 체크 된 예외를 던질 수 Runnable인스턴스가 없습니다

Java 설계자는 Runnable인터페이스 의 기능을 확장해야 할 필요성을 느꼈지만 인터페이스 사용에 영향을 미치고 싶지 Runnable않았을 수도 있습니다. 아마도 Callable이미 Java 1.5에서 별도의 인터페이스를 사용하는 이유 는 이미 기존 Runnable.


답변

Runnable과 Callable을 사용할 위치를 살펴 보겠습니다.

Runnable과 Callable은 모두 호출 스레드와 다른 스레드에서 실행됩니다. 그러나 Callable은 값을 반환하고 Runnable은 값을 반환 할 수 없습니다. 그래서 이것이 실제로 어디에 적용됩니까?

Runnable : 화재가 있고 작업을 잊어 버린 경우 Runnable을 사용하십시오. Runnable 안에 코드를 넣고 run () 메서드가 호출되면 작업을 수행 할 수 있습니다. 호출 스레드는 실제로 작업을 수행 할 때 중요하지 않습니다.

호출 가능 : 작업에서 값을 검색하려는 경우 호출 가능을 사용하십시오. 이제 스스로 호출 할 수는 없다. Callable을 감싸고 future.get ()에서 가치를 얻는 미래가 필요합니다. 여기서 호출 스레드는 Future가 결과로 돌아올 때까지 차단되며 결과적으로 Callable의 call () 메소드가 실행될 때까지 대기합니다.

따라서 Runnable 및 Callable 랩핑 메소드가 모두 정의 된 대상 클래스에 대한 인터페이스를 고려하십시오. 호출 클래스는 Runnable과 Callable을 모르는 인터페이스 메소드를 무작위로 호출합니다. Runnable 메소드는 Callable 메소드가 호출 될 때까지 비동기식으로 실행됩니다. 대상 클래스에서 값을 검색하기 때문에 호출 클래스의 스레드가 차단됩니다.

참고 : 대상 클래스 내에서 단일 스레드 실행기에서 Callable 및 Runnable을 호출 하여이 메커니즘을 직렬 디스패치 큐와 유사하게 만들 수 있습니다. 호출자가 Runnable 랩핑 된 메소드를 호출하는 한 호출 스레드는 차단하지 않고 실제로 빠르게 실행됩니다. Future 메소드에 Callable 랩핑 된 Callable을 호출하자마자 대기중인 다른 모든 항목이 실행될 때까지 차단해야합니다. 그래야만 메소드가 값과 함께 리턴됩니다. 이것은 동기화 메커니즘입니다.


답변

Callable인터페이스는 call()메소드를 선언 하고 Object 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반면 run()runnable을 사용하여 Thread를 작성하고 start ()를 호출 할 때 호출되는 메소드 를 선언 하는 인터페이스가 있습니다. 직접 run ()을 호출 할 수도 있지만 run () 메서드를 실행하는 것은 동일한 스레드입니다.

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();
}

몇 가지 주목할만한 차이점을 요약하면

  1. Runnable반면 객체는 결과를 반환하지 않는 Callable개체가 결과를 반환합니다.
  2. Runnable개체가 예외를 throw 할 수 있는 동안 개체는 확인 된 예외를 throw 할 수 없습니다 Callable.
  3. Runnable반면 인터페이스는 자바 1.0 이후 주변왔다 Callable에만 자바 1.5에서 소개되었습니다.

몇 가지 유사점 포함

  1. Runnable 또는 Callable 인터페이스를 구현하는 클래스의 인스턴스는 다른 스레드에 의해 잠재적으로 실행될 수 있습니다.
  2. Callable 및 Runnable 인터페이스의 인스턴스는 submit () 메소드를 통해 ExecutorService에 의해 실행될 수 있습니다.
  3. 둘 다 기능적 인터페이스이며 Java8 이후 Lambda 표현식에서 사용할 수 있습니다.

ExecutorService 인터페이스의 메소드는 다음과 같습니다.

<T> Future<T> submit(Callable<T> task);
Future<?> submit(Runnable task);
<T> Future<T> submit(Runnable task, T result);


답변

오라클 문서에서 이러한 인터페이스의 목적 :

실행 가능한 인터페이스는 인스턴스를 a로 실행하려는 모든 클래스에서 구현해야합니다 Thread. 클래스는라는 인수가없는 메소드를 정의해야합니다 run.

호출 가능 : 결과를 반환하고 예외가 발생할 수있는 작업입니다. 구현자는 call이라는 인수가없는 단일 메소드를 정의합니다. 이 Callable인터페이스는 Runnable인스턴스가 다른 스레드에 의해 잠재적으로 실행될 수있는 클래스를 위해 설계되었다는 점에서 와 비슷합니다 . Runnable그러나 A 는 결과를 반환하지 않으며 확인 된 예외를 throw 할 수 없습니다.

다른 차이점들 :

  1. ThreadRunnable 를 생성하도록 전달할 수 있습니다 . 그러나 매개 변수 로 전달하여 새 스레드를 만들 수는 없습니다 . Callable을 인스턴스 에만 전달할 수 있습니다 .CallableExecutorService

    예:

    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();
        }
    
    }
  2. Runnable화재에 사용 하고 전화를 잊어 버립니다. 사용 Callable결과를 확인 할 수 있습니다.

  3. Callable와 달리 invokeAll 메소드에 전달할 수 있습니다 Runnable. 가장 일반적으로 유용한 대량 실행 방법, 작업 모음을 실행 한 후 하나 이상이 완료되기를 기다리는 방법 invokeAnyinvokeAll수행

  4. 사소한 차이 : 구현할 메소드 이름 => run()for Runnableand call()for Callable.