ホームページ  >  記事  >  Java  >  ThreadPoolExecutor スレッド プールの Submit メソッド

ThreadPoolExecutor スレッド プールの Submit メソッド

巴扎黑
巴扎黑オリジナル
2017-06-26 11:33:072043ブラウズ

jdk1.7.0_79

前回の記事「ThreadPoolExecutorのスレッドプールの原理とその実行メソッド」で、スレッドプールThreadPoolExecutorの原理とその実行メソッドについて触れました。この記事では ThreadPoolExecutor#submit を分析します。

タスクの実行では、結果を返す必要がない場合もありますが、実行結果を返す必要があります。スレッドの場合、結果を返す必要がない場合は Runnable を実装でき、結果を実行する必要がある場合は Callable を実装できます。スレッド プールでは、execute は結果を返す必要のないタスクの実行も提供し、結果を返す必要があるタスクに対してその submit メソッドを呼び出すことができます。

ThreadPoolExecutorの継承関係を見直してください。

Executorインターフェースにはexecuteメソッドのみが定義されており、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 を実装するスレッドには戻り値がありません。つまり、上記の 3 つのメソッドのうち、submit(Callable task) は戻り値を取得でき、submit(Runnable) は戻り値を取得できません。 task、T result) can スレッドの戻り値は、受信キャリア結果を通じて間接的に取得されます。正確には、最後のメソッド submit (実行可能なタスク) には戻り値がありません。戻り値が得られてもnullになります。

submit メソッドの雰囲気をつかむために、以下に 3 つの例を示します。

submit(呼び出し可能なタスク)

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

submit(R不可能なタスク)

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 で定義されたジェネリック メソッドですが、AbstractExecutorService ではジェネリック メソッドではありません。戻り値はありません。 (Object、T、?の違いについては「JavaのObject、T(ジェネリック)、?の違い」を参照してください。)

上記のソースコードを見ると、これら 3 つのメソッドがほぼ同じであることがわかります。鍵となるのは、

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

タスクをパラメータとして newTaskFor に渡し、execute メソッドを呼び出し、最後に 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 はこれら 2 つのインターフェイスを実装しています。これは、非同期計算の結果を表し、実行用のスレッドとして Executor に渡すことができることを意味します。 FutureTask については、次の章で個別に分析します。したがって、この記事のスレッド プール ThreadPoolExecutor スレッド プールの submit メソッドの分析は完了していません。Java スレッドの Future モード (「14. Java の Future モード」) を理解する必要があります。

以上がThreadPoolExecutor スレッド プールの Submit メソッドの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。