>  기사  >  Java  >  ThreadPoolExecutor 스레드 풀의 제출 메소드

ThreadPoolExecutor 스레드 풀의 제출 메소드

巴扎黑
巴扎黑원래의
2017-06-26 11:33:072056검색

jdk1.7.0_79

 이전 글 "ThreadPoolExecutor 스레드 풀 원리와 그 실행 방법"에서 스레드 풀 ThreadPoolExecutor의 원리와 그 실행 방법에 대해 언급한 적이 있습니다. 이 기사에서는 ThreadPoolExecutor#submit을 분석합니다.

 작업을 실행하려면 결과를 반환할 필요가 없지만 실행 결과를 반환해야 하는 경우가 있습니다. 스레드의 경우 결과를 반환할 필요가 없으면 Runnable을 구현할 수 있고, 결과를 실행해야 하는 경우 Callable을 구현할 수 있습니다. 스레드 풀에서 실행은 결과를 반환할 필요가 없는 작업 실행도 제공하며, 결과를 반환해야 하는 작업의 경우 submit 메서드를 호출할 수 있습니다.

 ThreadPoolExecutor의 상속 관계를 검토하세요.

 

 Executor 인터페이스에는 실행 메소드만 정의되어 있고, ExecutorService 인터페이스에는 submit 메소드가 정의되어 있습니다.

 

//ExecutorServicepublic interface ExecutorService extends Executor {
  ...
  <T> Future<T> submit(Callable<T> task);
  <T> Future<T> submit(Runnable task, T result);
  <T> Future<T> submit(Runnable task);
  ...
}

  그리고 submit 메소드는 서브클래스 AbstractExecutorService에서 구현됩니다.

//AbstractExecutorServicepublic abstract class AbstractExecutorService implements ExecutorService {
  ...
  public <T> Future<T> submit(Callable<T> task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<T> ftask = newTaskFor(task);
    execute(ftask);
    return ftask;
  }
  public <T> Future<T> submit(Runnable task, T result) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<T> ftask = newTaskFor(task);
    execute(ftask);
    return ftask;
  }
  public Future<?> submit(Runnable task) {
    if (task == null) throw new NullPointerExeption();
    RunnableFuture<Void> ftask = newTaskFor(task, null);
    execute(ftask);
    return ftask; 
  }
  ...
}

 AbstractExecutorService에 구현된 submit 메소드는 실제로 submit 메소드의 알고리즘 뼈대를 정의하는 템플릿 메소드이며, 그 실행은 서브클래스에 넘겨진다. (많은 소스코드에서 템플릿 메소드 패턴이 널리 사용되고 있음을 알 수 있다. 템플릿 메소드 패턴은 "템플릿 메소드 패턴"을 참고한다.)

 submit 메소드는 스레드 실행의 반환값을 제공할 수 있지만, Callable이 구현된 경우에만 반환되며 Runnable을 구현하는 스레드에는 반환 값이 없습니다. 즉, 위의 세 가지 메서드 중 submit(Callable task)은 반환 값을 얻을 수 있으며 submit(Runnable) task, T 결과) 스레드의 반환 값은 들어오는 캐리어 결과를 통해 간접적으로 얻거나, 정확하게 말하면 처리를 위해 스레드에 넘겨집니다. 반환 값을 얻더라도 null입니다.

  제출 방법에 대한 느낌을 주기 위해 아래에 세 가지 예가 나와 있습니다.

  submit(Callable 작업)

package com.threadpoolexecutor;import java.util.concurrent.*;/**
 * ThreadPoolExecutor#sumit(Callable<T> task)
 * Created by yulinfeng on 6/17/17. */public class Sumit1 {public static void main(String[] args) throws ExecutionException, InterruptedException {
        Callable<String> callable = new Callable<String>() {public String call() throws Exception {
                System.out.println("This is ThreadPoolExetor#submit(Callable<T> task) method.");return "result";
            }
        };

        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<String> future = executor.submit(callable);
        System.out.println(future.get());
    }
}

 submit(실행 가능한 작업, T 결과)

package com.threadpoolexecutor;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;/**
 * ThreadPoolExecutor#submit(Runnable task, T result)
 * Created by yulinfeng on 6/17/17. */public class Submit2 {public static void main(String[] args) throws ExecutionException, InterruptedException {

        ExecutorService executor = Executors.newSingleThreadExecutor();
        Data data = new Data();
        Future<Data> future = executor.submit(new Task(data), data);
        System.out.println(future.get().getName());
    }
}class Data {
    String name;public String getName() {return name;
    }public void setName(String name) {this.name = name;
    }
}class Task implements Runnable {
    Data data;public Task(Data data) {this.data = data;
    }public void run() {
        System.out.println("This is ThreadPoolExetor#submit(Runnable task, T result) method.");
        data.setName("kevin");
    }
}

 제출(실행 가능한 작업)

package com.threadpoolexecutor;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;/**
 * ThreadPoolExecutor#sumit(Runnable runnables)
 * Created by yulinfeng on 6/17/17. */public class Submit {public static void main(String[] args) throws ExecutionException, InterruptedException {
        Runnable runnable = new Runnable() {public void run() {
                System.out.println("This is ThreadPoolExetor#submit(Runnable runnable) method.");
            }
        };

        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future future = executor.submit(runnable);
        System.out.println(future.get());
    }
}

위의 예를 보면 submit(Runnable runnable)을 호출할 때 정의된 타입이 필요하지 않다는 것을 알 수 있다. 즉, ExecutorService에 정의된 Generic 메소드이기는 하지만 AbstractExecutorService에서는 Generic 메소드가 아니기 때문이다. 반환 값이 없습니다. (Object, T, ?의 차이점은 "Java에서 Object, T(Generics), ?의 차이점"을 참조하세요.)

 위의 소스 코드에서 세 가지 메서드가 거의 동일하다는 것을 알 수 있습니다. 핵심은 다음과 같습니다.

RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);

  작업을 newTaskFor에 매개 변수로 전달한 다음 실행 메서드를 호출하고 마지막으로 ftask를 반환하는 방법 은 어떻게 되느냐?

//AbstractExecutorService#newTaskForprotected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
  return new FutureTask<T>(callable);
}
  protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
  return new FutureTask<T>(runnable, value);
}

  FutureTask 인스턴스가 반환된 것으로 보이며 FutureTask는 Future 및 Runnable 인터페이스를 구현합니다. Future 인터페이스는 비동기 계산에 사용할 수 있는 Java 스레드 Future 모드의 구현입니다. Runnable 인터페이스를 구현한다는 것은 스레드로 실행될 수 있음을 의미합니다. FutureTask는 이 두 인터페이스를 구현합니다. 이는 비동기 계산의 결과를 나타내고 실행을 위한 스레드로 Executor에 전달될 수 있음을 의미합니다. FutureTask는 다음 장에서 별도로 분석됩니다. 따라서 이 기사의 스레드 풀 ThreadPoolExecutor 스레드 풀의 제출 메소드에 대한 분석은 완료되지 않았습니다. Java 스레드의 미래 모드 - "14. Java의 미래 모드"를 이해해야 합니다.

위 내용은 ThreadPoolExecutor 스레드 풀의 제출 메소드의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.