문제

사용하는 것의 차이점은 무엇입니까? Runnable 그리고 Callable Java에서 동시 스레드를 설계할 때 인터페이스 중 하나를 선택하는 이유는 무엇입니까?

도움이 되었습니까?

해결책

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

Callable 인터페이스는 실행 가능과 유사합니다. 두 가지 모두 다른 스레드에 의해 인스턴스가 잠재적으로 실행되는 클래스를 위해 설계되었다는 점에서. 그러나 런 가능하면 결과를 반환하지 않으며 점검 된 예외를 던질 수 없습니다.

다른 팁

응용 분야의 차이점은 무엇입니까? Runnable 그리고 Callable. 현재의 반환 매개 변수와의 차이점입니다. Callable?

기본적으로 그렇습니다. 답변을 참조하십시오 이 질문. 그리고 Javadoc Callable.

둘 다 IF를 가져야 할 필요성은 무엇입니까? Callable 모든 것을 할 수 있습니다 Runnable 하다?

때문에 Runnable 상호 작용 할 수 없습니다 모든 것을하십시오 Callable 하다!

Runnable Java 1.0 이후 이후에 있었지만 Callable Java 1.5에서만 소개되었습니다. Runnable 지원하지 않습니다. 이론적으로 Java 팀은 Runnable.run() 방법, 그러나 이것은 1.5 이전 코드로 바이너리 호환성을 깨뜨 렸으며, 오래된 Java 코드를 최신 JVM으로 마이그 코딩 할 때 암석이 필요합니다. 그것은 큰 아니오입니다. Java는 거꾸로 호환되기 위해 노력하고 있습니다. 그리고 그것은 비즈니스 컴퓨팅을위한 Java의 가장 큰 판매 포인트 중 하나였습니다.

그리고 분명히 작업이없는 사용 사례가 있습니다. 필요 결과를 반환하거나 점검 된 예외를 던집니다. 이러한 사용 사례의 경우 사용 Runnable 사용하는 것보다 더 간결합니다 Callable<Void> 그리고 더미를 반환 (null) 값 call() 방법.

  • Callable 구현해야합니다 call() 방법 a Runnable 구현해야합니다 run() 방법.
  • Callable 값을 반환 할 수 있지만 a Runnable 할 수 없습니다.
  • Callable 점검 된 예외를 던질 수 있지만 a Runnable 할 수 없습니다.
  • Callable 함께 사용할 수 있습니다 ExecutorService#invokeXXX(Collection<? extends Callable<T>> tasks) 방법이지만 a Runnable 수 없습니다.

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

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

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

  • Callable<V> 인스턴스는 유형의 결과를 반환합니다 V, a Runnable 인스턴스가 아닙니다.
  • Callable<V> 인스턴스는 점검 된 예외를 던질 수 있지만 a Runnable 인스턴스는 할 수 없습니다

Java의 디자이너는 Runnable 인터페이스이지만 그들은 Runnable 인터페이스와 아마도 그것이 별도의 인터페이스를 사용한 이유 일 것입니다. Callable Java 1.5에서 이미 존재하는 것보다 Runnable.

런닝 가능하고 호출 가능한 위치를 살펴 보겠습니다.

실행 가능하고 호출 가능한 둘 다 호출 스레드와 다른 스레드에서 실행됩니다. 그러나 Callable은 값을 반환 할 수 있으며 런 가능성은 할 수 없습니다. 그래서 이것이 실제로 어디에 적용됩니까?

실행 가능 : 화재가 있고 작업을 잊어 버리면 런 가능성을 사용하십시오. 코드를 실행 가능한 안에 넣고 run () 메소드가 호출되면 작업을 수행 할 수 있습니다. 호출 스레드는 작업을 수행 할 때 실제로 신경 쓰지 않습니다.

호출 가능 : 작업에서 값을 검색하려는 경우 Callable을 사용하십시오. 이제 자체적으로 부를 수있는 것은 일을하지 않을 것입니다. 당신은 당신이 당신의 호출 가능성을 감싸고 미래에 당신의 가치를 얻는 미래가 필요합니다. get (). 여기서는 미래가 다시 발생할 때까지 호출 스레드가 차단 될 것입니다. 결과가 다시 발생하여 Callable의 Call () 메소드를 실행할 수 있습니다.

따라서 실행 가능하고 호출 가능한 랩핑 방법이 모두 정의 된 대상 클래스의 인터페이스에 대해 생각해보십시오. 호출 클래스는 어떤 실행 가능하고 호출 할 수 있는지 알지 못하는 인터페이스 메소드를 무작위로 호출합니다. 런 가능한 방법은 호출 가능한 방법이 호출 될 때까지 비동기 적으로 실행됩니다. 대상 클래스에서 값을 검색하기 때문에 호출 클래스의 스레드가 차단됩니다.

참고 : 대상 클래스 내에서 단일 스레드 executor에서 호출 가능하고 실행할 수 있으므로이 메커니즘을 직렬 디스패치 큐와 유사하게 만듭니다. 발신자가 런닝 가능한 랩핑 메소드를 호출하는 한, 호출 스레드는 차단하지 않고 실제로 빠르게 실행됩니다. 미래의 방법으로 랩핑 된 호출 가능한 전화를 받자 마자 다른 대기열 항목이 실행될 때까지 차단해야합니다. 그래야만 메소드는 값으로 반환됩니다. 이것은 동기화 메커니즘입니다.

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 반면에 선언하는 인터페이스가 있습니다 run() 실행 가능하고 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 객체는 결과를 반환하지 않지만 a Callable 객체는 결과를 반환합니다.
  2. Runnable 객체는 확인 된 예외를 던질 수 없습니다 Callable 물체는 예외를 던질 수 있습니다.
  3. 그만큼 Runnable 인터페이스는 Java 1.0 이후에 주변에있었습니다 Callable Java 1.5에서만 소개되었습니다.

몇 가지 유사점이 없습니다

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

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

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

Oracle 문서의 이러한 인터페이스의 목적 :

실행 가능 인터페이스는 인스턴스가 Thread. 클래스는 run.

호출 가능: 결과를 반환하고 예외를 던질 수있는 작업. 구현자는 Call이라는 인수가없는 단일 메소드를 정의합니다. 그만큼 Callable 인터페이스는 유사합니다 Runnable, 두 가지 모두 인스턴스가 다른 스레드에 의해 잠재적으로 실행되는 클래스를 위해 설계되었습니다. ㅏ Runnable, 그러나 결과를 반환하지 않으며 점검 된 예외를 던질 수 없습니다.

기타 차이점 :

  1. 당신은 통과 할 수 있습니다 Runnable a . 그러나 통과하여 새 스레드를 만들 수는 없습니다 Callable 매개 변수로. 당신은 전화 가능 만 전달할 수 있습니다 ExecutorService 인스턴스.

    예시:

    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. 행동 양식 invokeAny 그리고 invokeAll 가장 일반적으로 유용한 형태의 대량 실행을 수행하고 작업 모음을 실행 한 다음 적어도 하나 또는 전부를 기다리며 완료하십시오.

  4. 사소한 차이 : 구현할 방법 이름 => run() ~을 위한 Runnable 그리고 call() ~을 위한 Callable.

여기에서 이미 언급했듯이 Callable은 비교적 새로운 인터페이스이며 동시성 패키지의 일부로 도입되었습니다.Callable과 Runnable 모두 실행기와 함께 사용할 수 있습니다.Runnable 자체를 구현하는 클래스 스레드는 Runnable만 지원합니다.

실행기와 함께 Runnable을 계속 사용할 수 있습니다.실행자에게 전송하고 실행이 완료되면 업데이트될 미래 결과를 즉시 얻을 수 있다는 Callable의 장점.Runnable에서도 동일하게 구현될 수 있지만 이 경우 결과를 직접 관리해야 합니다.예를 들어 모든 결과를 보관할 결과 대기열을 만들 수 있습니다.다른 스레드는 이 대기열을 기다리고 도착하는 결과를 처리할 수 있습니다.

+-------------------------------------+--------------------------------------------------------------------------------------------------+
|              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 value of Type T                                                        |
| Can not throw Checked Exceptions    | Can throw Checked Exceptions                                                                     |
+-------------------------------------+--------------------------------------------------------------------------------------------------+

Java의 디자이너는 Runnable 인터페이스이지만 그들은 Runnable 인터페이스와 아마도 그것이 별도의 인터페이스를 사용한 이유 일 것입니다. Callable Java 1.5에서 이미 존재하는 것보다 Runnable Java 1.0 이후 Java의 일부인 인터페이스. 원천

호출 가능과 런 가능의 차이점은 다음과 같습니다.

  1. Callable은 JDK 5.0에 도입되었지만 Runnable은 JDK 1.0에서 소개됩니다.
  2. Callable에는 Call () 메소드가 있지만 runnable은 run () 메소드가 있습니다.
  3. Callable에는 값을 반환하지만 runnable에는 값을 반환하지 않는 실행 방법이 있습니다.
  4. 통화 방법은 확인 된 예외를 던질 수 있지만 실행 메소드는 확인 된 예외를 던질 수 없습니다.
  5. Callable 사용 제출 () 메소드는 작업 대기열을 넣지 만 실행 가능한 사용 execute () 메소드를 작업 대기열에 넣습니다.

전화 가능하고 실행 가능 둘 다 서로 비슷하며 스레드 구현에 사용할 수 있습니다. 구현시 실행 가능 당신은 구현해야합니다 운영() 방법이지만 호출 가능한 경우 구현해야합니다. 전화() 방법, 두 방법 모두 비슷한 방식으로 작동하지만 호출 가능 전화() 방법은 유연성이 더 많으며, 그들 사이에는 약간의 차이가 있습니다.

차이 실행 가능 그리고 호출 가능 아래--

1) 운영() 의 방법 실행 가능 보고 무효의, 당신이 당신의 스레드가 당신이 더 사용할 수있는 무언가를 반환하기를 원한다면 Runnable Run ()의 선택 없음 방법. 해결책이 있습니다 '전화 가능', 당신이 어떤 것을 형태로 반환하고 싶다면 물체 그럼 당신 실행 가능한 대신 호출 가능을 사용해야합니다. 호출 가능한 인터페이스에는 메소드가 있습니다 객체를 반환하는 'Call ()'.

메소드 서명 - runnable->

public void run(){}

Callable->

public Object call(){}

2) Runnable Run () 방법 확인 된 예외가 발생하면해야합니다 시도 캐치 블록으로 처리해야합니다, 그러나 Callable Call () 방법 확인 된 예외를 던질 수 있습니다 아래

 public Object call() throws Exception {}

3) 실행 가능 유산에서 나옵니다 Java 1.0 버전이지만 호출 가능 와서 Java 1.5 버전 임원 뼈대.

당신이 익숙하다면 집행자 그럼 당신은해야합니다 실행 가능한 대신 호출 가능을 사용하십시오.

당신이 이해하기를 바랍니다.

실행 가능 (VS) 호출 가능 우리가 Executer 프레임 워크를 사용할 때 시점에 들어옵니다.

ExecutorService는의 하위 인터페이스입니다 Executor, 이는 실행 가능하고 부름 가능한 작업을 모두 받아들입니다.

인터페이스를 사용하여 이전 멀티 스레딩을 달성 할 수 있습니다 Runnable1.0 이후, 그러나 여기서 문제는 스레드 작업을 완료 한 후 스레드 정보를 수집 할 수 없습니다. 데이터를 수집하기 위해 정적 필드를 사용할 수 있습니다.

각 학생 데이터를 수집 할 별도의 스레드 예제.

static HashMap<String, List> multiTasksData = new HashMap();
public static void main(String[] args) {
    Thread t1 = new Thread( new RunnableImpl(1), "T1" );
    Thread t2 = new Thread( new RunnableImpl(2), "T2" );
    Thread t3 = new Thread( new RunnableImpl(3), "T3" );

    multiTasksData.put("T1", new ArrayList() ); // later get the value and update it.
    multiTasksData.put("T2", new ArrayList() );
    multiTasksData.put("T3", new ArrayList() );
}

이 문제를 해결하기 위해 그들이 소개했습니다 Callable<V>1.5 이후 결과를 반환하고 예외를 던질 수 있습니다.

  • 단일 초록 방법 : Callable 및 Runnable 인터페이스 모두 단일 추상 방법이 있으며, 이는 Java 8의 Lambda 표현식에서 사용할 수 있음을 의미합니다.

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

실행을위한 작업을 위임하는 몇 가지 방법이 있습니다. ExecutorService.

  • execute(Runnable task):void 새 스레드를 상자하지만이 메소드가 void를 반환 할 때 메인 스레드 또는 발신자 스레드를 차단하지 않습니다.
  • submit(Callable<?>):Future<?>, submit(Runnable):Future<?> 새로운 스레드를 상자하고 사용할 때 메인 스레드를 차단합니다. Future.get ().

executor 프레임 워크와 함께 호출 가능한 인터페이스 사용의 예.

class CallableTask implements Callable<Integer> {
    private int num = 0;
    public CallableTask(int num) {
        this.num = num;
    }
    @Override
    public Integer call() throws Exception {
        String threadName = Thread.currentThread().getName();
        System.out.println(threadName + " : Started Task...");

        for (int i = 0; i < 5; i++) {
            System.out.println(i + " : " + threadName + " : " + num);
            num = num + i;
            MainThread_Wait_TillWorkerThreadsComplete.sleep(1);
        }
        System.out.println(threadName + " : Completed Task. Final Value : "+ num);

        return num;
    }
}
class RunnableTask implements Runnable {
    private int num = 0;
    public RunnableTask(int num) {
        this.num = num;
    }
    @Override
    public void run() {
        String threadName = Thread.currentThread().getName();
        System.out.println(threadName + " : Started Task...");

        for (int i = 0; i < 5; i++) {
            System.out.println(i + " : " + threadName + " : " + num);
            num = num + i;
            MainThread_Wait_TillWorkerThreadsComplete.sleep(1);
        }
        System.out.println(threadName + " : Completed Task. Final Value : "+ num);
    }
}
public class MainThread_Wait_TillWorkerThreadsComplete {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        System.out.println("Main Thread start...");
        Instant start = java.time.Instant.now();

        runnableThreads();
        callableThreads();

        Instant end = java.time.Instant.now();
        Duration between = java.time.Duration.between(start, end);
        System.out.format("Time taken : %02d:%02d.%04d \n", between.toMinutes(), between.getSeconds(), between.toMillis()); 

        System.out.println("Main Thread completed...");
    }
    public static void runnableThreads() throws InterruptedException, ExecutionException {
        ExecutorService executor = Executors.newFixedThreadPool(4);
        Future<?> f1 = executor.submit( new RunnableTask(5) );
        Future<?> f2 = executor.submit( new RunnableTask(2) );
        Future<?> f3 = executor.submit( new RunnableTask(1) );

        // Waits until pool-thread complete, return null upon successful completion.
        System.out.println("F1 : "+ f1.get());
        System.out.println("F2 : "+ f2.get());
        System.out.println("F3 : "+ f3.get());

        executor.shutdown();
    }
    public static void callableThreads() throws InterruptedException, ExecutionException {
        ExecutorService executor = Executors.newFixedThreadPool(4);
        Future<Integer> f1 = executor.submit( new CallableTask(5) );
        Future<Integer> f2 = executor.submit( new CallableTask(2) );
        Future<Integer> f3 = executor.submit( new CallableTask(1) );

        // Waits until pool-thread complete, returns the result.
        System.out.println("F1 : "+ f1.get());
        System.out.println("F2 : "+ f2.get());
        System.out.println("F3 : "+ f3.get());

        executor.shutdown();
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top