>  기사  >  Java  >  Java 멀티스레딩의 Callable 및 Future에 대한 자세한 소개(코드 예)

Java 멀티스레딩의 Callable 및 Future에 대한 자세한 소개(코드 예)

不言
不言앞으로
2019-02-11 11:01:412754검색

이 기사는 Java 멀티스레딩의 Callable 및 Future에 대한 자세한 소개(코드 예제)를 제공합니다. 필요한 친구가 참고할 수 있기를 바랍니다.

Callable과 Future가 등장하는 이유

스레드를 생성하는 방법에는 두 가지가 있는데, 하나는 Thread를 직접 상속하는 방법이고, 다른 하나는 Runnable 인터페이스를 구현하는 방법입니다.
이 두 가지 방법에는 결함이 있습니다. 작업을 완료한 후에 실행 결과를 얻을 수 없습니다.
실행 결과를 얻으려면 공유 변수나 스레드 통신을 통해 효과를 얻어야 하는데, 이는 사용하기가 더 번거롭습니다.
Java 1.5부터는 태스크 실행이 완료된 후 태스크 실행 결과를 얻을 수 있는 Callable과 Future를 제공하고 있습니다.

Callable 및 Future 소개

Callable 인터페이스는 호출할 수 있고 결과를 반환하는 코드 조각을 나타냅니다. Future 인터페이스는 아직 완료되지 않은 작업에 의해 제공되는 미래 결과인 비동기 작업을 나타냅니다. . 따라서 Callable은 결과를 생성하는 데 사용되고 Future는 결과를 얻는 데 사용됩니다.
Callable 인터페이스는 제네릭을 사용하여 반환 유형을 정의합니다. Executors 클래스는 스레드 풀의 Callable 내에서 작업을 실행하는 데 유용한 몇 가지 메서드를 제공합니다. Callable 작업은 병렬이므로(병렬이란 전체가 병렬로 보인다는 의미입니다. 실제로는 특정 시점에 단 하나의 스레드만 실행됩니다) 반환되는 결과를 기다려야 합니다.
java.util.concurrent.Future 객체는 이 문제를 해결해 줍니다. 스레드 풀이 Callable 작업을 제출한 후 Future 개체가 반환됩니다. 이를 사용하여 Callable 작업의 상태를 확인하고 Callable에서 반환된 실행 결과를 얻을 수 있습니다. Future는 Callable이 종료될 때까지 기다렸다가 실행 결과를 얻을 수 있도록 get() 메서드를 제공합니다.

Callable and Runnable

java.lang.Runnable, 인터페이스이고 여기에는 단 하나의 run() 메서드만 선언됩니다.

public interface Runnable {
    public abstract void run();
}

run() 메서드의 반환 값은 void 유형이므로 실행 중 작업을 완료한 후에는 결과가 반환될 수 없습니다.

 Callable은 java.util.concurrent 패키지 아래에 있으며 인터페이스이기도 하며, 그 안에는 하나의 메소드만 선언되어 있는데 이 메소드를 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;
}

이것은 일반 인터페이스인 call()입니다. function 반환된 유형은 전달된 V 유형입니다.

Callable

사용은 일반적으로 ExecutorService와 함께 사용됩니다. submit 메소드의 여러 오버로드된 버전이 ExecutorService 인터페이스에 선언됩니다.

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

첫 번째 submit 메소드의 매개변수 유형은 Callable입니다.

당분간 Callable은 일반적으로 ExecutorService와 결합하여 사용된다는 점만 알아두시면 됩니다.

일반적으로 첫 번째 제출 방법과 세 번째 제출 방법을 사용하며 두 번째 제출 방법은 거의 사용되지 않습니다.

Future

Future는 특정 Runnable 또는 Callable 작업의 실행 결과를 취소하고 완료 여부를 쿼리하여 결과를 얻는 것입니다. 필요한 경우 작업이 결과를 반환할 때까지 차단되는 get 메서드를 통해 실행 결과를 얻을 수 있습니다.

Future 클래스는 java.util.concurrent 패키지 아래에 있습니다.

public interface Future<V> {
    boolean cancel(boolean mayInterruptIfRunning);
    boolean isCancelled();
    boolean isDone();
    V get() throws InterruptedException, ExecutionException;
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}
는 Future 인터페이스에서 5개의 메소드를 선언합니다. 각 메소드의 기능은 아래에서 차례로 설명됩니다.
  • Cancel 메소드는 다음과 같습니다. 작업 취소에 사용됩니다. 작업 취소에 성공하면 true를 반환하고, 작업 취소에 실패하면 false를 반환합니다. mayInterruptIfRunning 매개변수는 실행 중이지만 완료되지 않은 작업을 취소할 수 있는지 여부를 나타냅니다. true로 설정하면 실행 중인 작업을 취소할 수 있다는 의미입니다. 작업이 완료되면 mayInterruptIfRunning이 true인지 false인지에 관계없이 이 메서드는 확실히 false를 반환합니다. 즉, 완료된 작업이 취소되면 작업이 실행 중이고 mayInterruptIfRunning이 true로 설정된 경우 false를 반환합니다. mayInterruptIfRunning이 false로 설정된 경우 true를 반환하고 작업이 실행되지 않은 경우 mayInterruptIfRunning이 true인지 false인지에 관계없이 false를 반환합니다.

  • isCancelled 메서드는 작업이 성공적으로 취소되었는지 여부를 나타냅니다. 작업이 정상적으로 완료되기 전에 작업이 성공적으로 취소되면 true를 반환합니다.

  • isDone 메서드는 작업이 완료되었는지 여부를 나타냅니다. 작업이 완료되면

  • get() 메서드가 사용되어 차단이 발생합니다.

  • get(long timeout, TimeUnit 단위)을 사용하여 지정된 시간 내에 결과를 얻지 못하면 바로 null을 반환합니다.

Future는 세 가지 기능을 제공합니다.
  1. 작업 완료 여부를 확인하고

  2. 작업을 중단하고

  3. 작업 실행 결과를 얻습니다.

    Future는 단순한 인터페이스이기 때문에 객체 생성에 직접 사용할 수 없으므로 다음과 같은 FutureTask가 있습니다.

    FutureTask

    FutureTask는 RunnableFuture 인터페이스를 구현합니다.
public interface RunnableFuture<V> extends Runnable, Future<V> {  
    void run();  
}

이 인터페이스는 Runnable 및 Future 인터페이스를 구현하며 인터페이스의 특정 구현은 FutureTask에 의해 구현됩니다. 이 클래스의 두 가지 구성 방법은 다음과 같습니다.

public FutureTask(Callable<V> callable) {  
        if (callable == null)  
            throw new NullPointerException();  
        sync = new Sync(callable);  
    }  
    public FutureTask(Runnable runnable, V result) {  
        sync = new Sync(Executors.callable(runnable, result));  
    }

如上提供了两个构造函数,一个以Callable为参数,另外一个以Runnable为参数。这些类之间的关联对于任务建模的办法非常灵活,允许你基于FutureTask的Runnable特性(因为它实现了Runnable接口),把任务写成Callable,然后封装进一个由执行者调度并在必要时可以取消的FutureTask。

FutureTask可以由执行者调度,这一点很关键。它对外提供的方法基本上就是Future和Runnable接口的组合:get()、cancel、isDone()、isCancelled()和run(),而run()方法通常都是由执行者调用,我们基本上不需要直接调用它。

FutureTask的例子
public class MyCallable implements Callable<String> {  
    private long waitTime;   
    public MyCallable(int timeInMillis){   
        this.waitTime=timeInMillis;  
    }  
    @Override  
    public String call() throws Exception {  
        Thread.sleep(waitTime);  
        //return the thread name executing this callable task  
        return Thread.currentThread().getName();  
    }  

}
public class FutureTaskExample {  
     public static void main(String[] args) {  
        MyCallable callable1 = new MyCallable(1000);                       // 要执行的任务  
        MyCallable callable2 = new MyCallable(2000);  

        FutureTask<String> futureTask1 = new FutureTask<String>(callable1);// 将Callable写的任务封装到一个由执行者调度的FutureTask对象  
        FutureTask<String> futureTask2 = new FutureTask<String>(callable2);  

        ExecutorService executor = Executors.newFixedThreadPool(2);        // 创建线程池并返回ExecutorService实例  
        executor.execute(futureTask1);  // 执行任务  
        executor.execute(futureTask2);    

        while (true) {  
            try {  
                if(futureTask1.isDone() && futureTask2.isDone()){//  两个任务都完成  
                    System.out.println("Done");  
                    executor.shutdown();                          // 关闭线程池和服务   
                    return;  
                }  

                if(!futureTask1.isDone()){ // 任务1没有完成,会等待,直到任务完成  
                    System.out.println("FutureTask1 output="+futureTask1.get());  
                }  

                System.out.println("Waiting for FutureTask2 to complete");  
                String s = futureTask2.get(200L, TimeUnit.MILLISECONDS);  
                if(s !=null){  
                    System.out.println("FutureTask2 output="+s);  
                }  
            } catch (InterruptedException | ExecutionException e) {  
                e.printStackTrace();  
            }catch(TimeoutException e){  
                //do nothing  
            }  
        }  
    }  
}

위 내용은 Java 멀티스레딩의 Callable 및 Future에 대한 자세한 소개(코드 예)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 segmentfault.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제