source

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

goodcode 2022. 8. 18. 23:29
반응형

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

무엇 차이는 무엇입니까 경우의는을 사용하는 간의 차이는 무엇입니까?Runnable그리고 그리고.Callable인터페이슬 때 자바에서를 동시에 실을 디자인은 왜 한가지 일을 선택할 것인가?Java에서 동시 스레드를설계할때 인터페이스가 있는데, 왜 다른 스레드를 다른 스레드보다 선택하는이유는 무엇입니까?

자세한 것은 이쪽을 참조해 주세요.

Callable 인터페이스는 Runnable과 비슷하지만 둘 다 다른 스레드에 의해 인스턴스가 실행될 수 있는 클래스를 위해 설계되어 있습니다.그러나 Runnable은 결과를 반환하지 않으며 선택된 예외를 슬로우할 수 없습니다.

무엇 응용프로그램의 차이점은 무엇입니까의 응용 프로그램에서 차이가 있을까?Runnable그리고 그리고.Callable에 있는에. 그 차이만 반환 매개 변수 현재 반환 파라미터와의 차이뿐입니까?Callable

기본적으로, 네.질문에 대한 답변을 참조하십시오.및 의 javadoc.

만약 이 이유는 무엇입니까 필요한가지가 모두 두 둘 다를 갖고 있는 것이 필요하다?Callable그 모든 것을 할 수 그 모든 것을 할 수 있있다Runnable?그렇습니까나요?

그 왜냐하면 왜냐하면Runnable인터페이스가 모든 것을 할 수 있는 것은 아닙니다.Callable!있달 거야!

Runnable주변에 자바 1.0,지만 자바 1.0부터 있었지만부터 있었던 것 같은데요Callable오직 자바 1.5쌍으로...자바 1.5에서만 도입되었습니다 유스 케이스 처리하기 위해 도입되었다.Runnable지원하지 않습니다.을 사용하다은 "Java"의.Runnable.run()그러나 이로 인해 1.5 이전 코드와의 바이너리 호환성이 손상되어 오래된 Java 코드를 새로운 JVM으로 이행할 때 레코딩이 필요합니다.안 된다 자바어Java는 비즈니스 컴퓨팅의 가장 큰 세일즈 포인트 중 하나입니다.

또한 태스크가 결과를 반환하거나 선택된 예외를 발생시킬 필요가 없는 사용 사례도 있습니다.이러한 유스케이스의 경우,Runnable Callable<Void>null입니다.call()★★★★★★ 。

  • A Callable할 가 있다call() 중 메서드Runnable할 가 있다run()★★★★★★ 。
  • A Callable할 수 " "는 반환할 수 없습니다.Runnable하다.
  • A Callable 할 수 , 「」는 「」입니다.Runnable하다.
  • A Callable 함께 할 수 .ExecutorService#invokeXXX(Collection<? extends Callable<T>> tasks)단, 「」입니다.Runnable그럴 리가 없어요

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

다른 블로그에서 이 차이를 좀 더 자세히 설명할 수 있습니다.

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

  • A Callable<V>는 instance 유형의 합니다.V a, a는Runnable는 그렇지 않습니다
  • A Callable<V>는 체크된 할 수 , 「」의 경우는, 「」의 예외입니다.Runnable는 할 수 없다

은 Java의 .Runnable 다만, 을 주는 것은 않았습니다.Runnable 그것이 이 ''라는 이름의 된 이다.Callable1.보다 더 많은 정보를 얻을 수 있습니다.Runnable.

Runnable과 Callable을 사용할 수 있는 곳을 살펴보겠습니다.

Runnable과 Callable은 모두 호출 스레드와는 다른 스레드에서 실행됩니다.그러나 Callable은 값을 반환할 수 있지만 Runnable은 반환할 수 없습니다.그럼 이게 실제로 어디에 적용되는 거죠?

[Runnable] : 기동 후 잊어버리는 작업이 있는 경우 [Runnable]를 사용합니다.Runnable에 코드를 넣으면 run() 메서드가 호출되면 작업을 수행할 수 있습니다.호출 스레드는 작업을 수행할 때 실제로 중요하지 않습니다.

Callable : 태스크에서 값을 가져오려는 경우 Callable을 사용합니다.이제 콜러블만으로는 그 일을 할 수 없다.콜러블을 정리하고 Future.get()에 대한 가치를 얻을 수 있는 미래가 필요합니다.여기서 호출 스레드는 Future가 Callable의 call() 메서드가 실행되기를 기다리는 결과를 반환할 때까지 차단됩니다.

Runnable 메서드와 Callable 메서드가 모두 정의되어 있는 타깃클래스에 대한 인터페이스에 대해 생각해 보겠습니다.호출 클래스는 어떤 것이 실행 가능이고 어떤 것이 콜 가능인지 알 수 없는 인터페이스 메서드를 랜덤으로 호출합니다.Runnable 메서드는 Callable 메서드가 호출될 때까지 비동기적으로 실행됩니다.여기서 대상 클래스에서 값을 검색 중이므로 호출 클래스의 스레드가 차단됩니다.

메모: 타깃 클래스 내에서는 단일 스레드 실행기에서 콜 가능 및 실행 가능에 대한 콜을 발신할 수 있습니다.이 메커니즘은 시리얼 디스패치 큐와 비슷합니다.따라서 발신자가 Runnable 랩된 메서드를 호출하는 한 호출 스레드는 차단 없이 매우 빠르게 실행됩니다.Future로 랩된 Callable 메서드를 호출하면 큐에 있는 다른 모든 항목이 실행될 때까지 차단해야 합니다.그런 다음 메서드가 값과 함께 반환됩니다.이것은 동기 메커니즘입니다.

Callable가 「 「」를 선언합니다.call()및콜()의은 method "call()" generics"를 반환해야 .

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, 인터페이스에서는, 「Dada」, 「Diagnostics」, 「Diagnostics」, 「Diagnostics」, 「Diagnostics」를 선언합니다.run()스레드를 ()를 호출했을 때 .run은 동일한입니다.run()은 run()의 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. A Runnable하지 않는 , 「」는 반환되지 않습니다.Callableobject를 합니다.
  2. A Runnable개체는 선택된 예외를 헤라로 슬로우할 수 없습니다.Callable오브젝트는 예외를 발생시킬 수 있습니다.
  3. Runnable1.해 온 반면 Java 1.0부터 존재했습니다.Callable 1되었습니다.

다음과 같은 유사점이 거의 없습니다.

  1. Runnable 또는 Callable 인터페이스를 구현하는 클래스의 인스턴스는 다른 스레드에 의해 실행될 수 있습니다.
  2. Callable 인터페이스와 Runnable 인터페이스 양쪽의 인스턴스는 Submit() 메서드를 통해 Executor Service에 의해 실행할 수 있습니다.
  3. 둘 다 기능 인터페이스이며 Java8 이후 람다 식에서 사용할 수 있습니다.

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

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

oracle 매뉴얼에 기재되어 있는 인터페이스의 목적은 다음과 같습니다.

실행 가능한 인터페이스는 instance가 실행되는 모든 클래스에서 구현해야 합니다.Thread. 이 메서드는 인수 없음입니다.run.

호출 가능:결과를 반환하고 예외를 발생시킬 수 있는 태스크입니다.구현자는 call이라는 인수를 사용하지 않고 단일 메서드를 정의합니다.Callable는 '이러다'와 .Runnable둘 다 다른 스레드에 의해 인스턴스가 실행될 수 있는 클래스용으로 설계되어 있습니다. a.Runnable단, 는 결과를 반환하지 않으며 선택된 예외를 슬로우할 수 없습니다.

기타 차이점:

  1. 할 수 Runnable스레드를 만듭니다.그러나 통과를 통해 새 스레드를 만들 수 없습니다.Callable파라미터로 지정합니다.은 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에서도 동일한 기능을 구현할 수 있지만 이 경우 사용자가 직접 결과를 관리해야 합니다.예를 들어, 모든 결과를 보관하는 결과 대기열을 생성할 수 있습니다.다른 스레드는 이 큐에서 대기하여 도착한 결과를 처리할 수 있습니다.

Callable과 Runnable의 차이는 다음과 같습니다.

  1. 콜 가능은 JDK 5.0에 도입되어 있습니다만, Runnable은 JDK 1.0에 도입되어 있습니다.
  2. Callable에는 call() 메서드가 있지만 Runnable에는 run() 메서드가 있습니다.
  3. Callable에는 값을 반환하는 콜 메서드가 있지만 Runnable에는 값을 반환하지 않는 실행 메서드가 있습니다.
  4. 호출 메서드는 선택된 예외를 슬로우할 수 있지만 실행 메서드는 선택된 예외를 슬로우할 수 없습니다.
  5. 콜 가능은 작업 큐에 넣기 위해 submit() 메서드를 사용하지만 Runnable은 작업 큐에 넣기 위해 execute() 메서드를 사용합니다.
+----------------------------------------+--------------------------------------------------------------------------------------------------+
|              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 |                                                                     |
+----------------------------------------+--------------------------------------------------------------------------------------------------+

은 Java의 .Runnable 다만, 을 주는 것은 않았습니다.Runnable 그것이 이 ''라는 이름의 된 이다.Callable1.보다 더 많은 정보를 얻을 수 있습니다.RunnableJava 1.0 소스 이후 Java의 일부였던 인터페이스

콜 가능과 실행 가능은 모두 유사하며 스레드 구현에 사용할 수 있습니다.Runnable을 구현하는 경우 run() 메서드를 구현해야 하지만 call() 메서드를 구현해야 합니다.두 메서드는 같은 방법으로 동작하지만 callable call() 메서드는 더 유연합니다.그들 사이에는 몇 가지 차이점이 있다.

RunnableCallable의 차이는 다음과 같습니다.

1) runnable의 run() 메서드는 void를 반환합니다.즉, 스레드가 더 이상 사용할 수 있는 것을 반환하려면 Runnable run() 메서드를 사용할 수 없습니다.'콜 가능' 솔루션이 있습니다. 객체의 형태로 반환하려면 Runnable 대신 Callable을 사용해야 합니다.콜 가능 인터페이스에는 오브젝트를 반환하는 메서드 'call()'가 있습니다.

메서드 시그니처 - 실행 가능 ->

public void run(){}

콜 가능 ->

public Object call(){}

2) Runnable run() 메서드의 경우 체크된 예외가 발생하면 try catch block으로 처리해야 하지만 Callable call() 메서드의 경우 체크된 예외를 다음과 같이 던질 수 있습니다.

 public Object call() throws Exception {}

3) Runnable레거시 Java 1.0 버전이지만 콜 가능은 Executer 프레임워크가 포함Java 1.5 버전입니다.

Executer에 대해 잘 알고 있는 경우 Runnable 대신 Callable을 사용해야 합니다.

이해해주길 바라.

실행 가능 (vs) 실행 가능 (vs) 실행 가능 (callable)은 실행 가능 프레임워크를 사용할 때 중요합니다.

Executor Service는 의 서브 인터페이스로 실행 가능 태스크와 호출 가능 태스크를 모두 받아들입니다.

이전의 멀티스레딩은 인터페이스를 사용하여 실행할 수 있지만, 여기서는 스레드 태스크를 완료한 후 스레드 정보를 수집할 수 없습니다.데이터를 수집하기 위해 Static 필드를 사용할 수 있습니다.

예: 스레드를 분리하여 각 학생 데이터를 수집합니다.

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

이 문제를 해결하기 위해 결과를 반환하고 예외를 발생시킬 수 있는 방법을 도입했습니다.

  • Single Abstract Method : Callable 인터페이스와 Runnable 인터페이스 모두 단일 Abstract Method가 있습니다.즉, Java 8의 람다 식에서 사용할 수 있습니다.

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

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

  • execute(Runnable task):void는 새 스레드를 포장하지만 이 메서드가 무효를 반환하기 때문에 메인 스레드 또는 발신자 스레드를 차단하지 않습니다.
  • submit(Callable<?>):Future<?>,submit(Runnable):Future<?>future.get 사용 시 새로운 스레드를 crates하여 메인스레드를 차단합니다.

실행 가능, 실행 가능, 호출 가능 및 실행자 프레임워크를 사용한 인터페이스 사용 예.

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

이것은 기능 프로그래밍과 일치하는 인터페이스 명명 규칙의 일종입니다.

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

다른 모든 답변과 함께:

Callable을 개별 스레드에 전달/사용할 수 없습니다.콜 가능은 실행자 프레임워크에서만 사용할 수 있습니다.그러나 Runnable은 실행을 위해 개별 스레드(new Thread(new Custom Runnable())로 전달될 수 있을 뿐만 아니라 Executor Framework에서도 사용할 수 있습니다.

언급URL : https://stackoverflow.com/questions/141284/the-difference-between-the-runnable-and-callable-interfaces-in-java

반응형