web-dev-qa-db-ja.com

JavaのこのコードのExecutorService.submitとExecutorService.executeの違いは何ですか?

ExectorServiceを使用してthreadsをプールし、タスクを送信することを学んでいます。私は以下の簡単なプログラムを持っています

import Java.util.concurrent.ExecutorService;
import Java.util.concurrent.Executors;
import Java.util.concurrent.TimeUnit;


class Processor implements Runnable {

    private int id;

    public Processor(int id) {
        this.id = id;
    }

    public void run() {
        System.out.println("Starting: " + id);

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            System.out.println("sorry, being interupted, good bye!");
            System.out.println("Interrupted "+Thread.currentThread().getName());
            e.printStackTrace();    
        }

        System.out.println("Completed: " + id);
    }
}


public class ExecutorExample {

    public static void main(String[] args) {
        Boolean isCompleted=false;

        ExecutorService executor = Executors.newFixedThreadPool(2);

        for(int i=0; i<5; i++) {
            executor.execute(new Processor(i));
        }

        //executor does not accept any more tasks but the submitted tasks continue
        executor.shutdown();

        System.out.println("All tasks submitted.");

        try {
            //wait for the exectutor to terminate normally, which will return true
            //if timeout happens, returns false, but this does NOT interrupt the threads
            isCompleted=executor.awaitTermination(100, TimeUnit.SECONDS);
            //this will interrupt thread it manages. catch the interrupted exception in the threads 
            //If not, threads will run forever and executor will never be able to shutdown.
            executor.shutdownNow();
        } catch (InterruptedException e) {
        }

        if (isCompleted){
        System.out.println("All tasks completed.");
       }
        else {
            System.out.println("Timeout "+Thread.currentThread().getName());
        }
    }
        }

派手なことは何もしませんが、2つのthreadsを作成し、合計5つのタスクを送信します。各threadがタスクを完了すると、次のタスクを取ります。上記のコードでは、executor.submitを使用します。また、executor.executeに変更しました。しかし、出力に違いは見られません。 submit and executeメソッドはどのように異なりますか?これはAPIが言うこと

メソッドsubmitは、実行のキャンセルや完了の待機に使用できるFutureを作成して返すことにより、ベースメソッドExecutor.execute(Java.lang.Runnable)を拡張します。メソッドinvokeAnyおよびinvokeAllは、最も一般的に有用な形式の一括実行を実行し、タスクのコレクションを実行してから、少なくとも1つまたはすべてが完了するまで待機します。 (Class ExecutorCompletionServiceを使用して、これらのメソッドのカスタマイズされたバリアントを作成できます。)

しかし、それが正確に何を意味するのかは私には明らかではありませんか?

46
brain storm

JavaDocからわかるように、execute(Runnable)は何も返しません。

ただし、submit(Callable<T>)Futureオブジェクトを返します。これにより、実行中のスレッドを後でプログラムでキャンセルし、Tが返されたときに返されるCallableを取得できます。完了します。詳細については、 JavaDoc of Future を参照してください

_Future<?> future = executor.submit(longRunningJob);
...
//long running job is taking too long
future.cancel(true);
_

さらに、future.get() == nullが例外をスローしない場合、Runnableは正常に実行されました

45
dkatzel

違いは、executeは単純にタスクを開始するだけで、submitはタスクを管理するFutureオブジェクトを返すことです。 Futureオブジェクトを使用して、次のことを実行できます。

  • cancelメソッドを使用して、タスクを途中でキャンセルします。
  • getを使用して、タスクの実行が完了するまで待ちます。

Futureインターフェースは、Callableをプールに送信する場合により便利です。 callメソッドの戻り値は、Future.getを呼び出すと返されます。 Futureへの参照を維持しない場合、違いはありません。

43
tbodt

_execute:_呼び出しに使用し、呼び出しを忘れる

_submit:_これを使用して、メソッド呼び出しの結果を検査し、呼び出しによって返されたFutureオブジェクトに対して適切なアクションを実行します

主な違い:Exceptionの処理

submit()は、フレームワーク自体で未処理のExceptionを非表示にします。

execute()は未処理のExceptionをスローします。

submit()を使用して例外を処理するためのソリューション

  1. _Callable or Runnable code in try{} catch{} block_をラップします

    OR

  2. future.get() call in try{} catch{} blockを保持

    OR

  3. 独自のThreadPoolExecutorを実装し、afterExecuteメソッドをオーバーライドします

ツアーの他のクエリについて

invokeAll

指定されたタスクを実行し、すべての完了またはタイムアウトが期限切れになった時点で、ステータスと結果を保持するFutureのリストを返します。

invokeAny

指定されたタスクが実行され、指定されたタイムアウトが経過する前に正常に完了したタスクの結果が返されます(例外がスローされない場合)。

送信されたすべてのタスクが完了するまで待機する場合は、invokeAllを使用します。

N個の送信済みタスクから1つのタスクを正常に完了したい場合は、invokeAnyを使用します。この場合、タスクの1つが正常に完了すると、進行中のタスクはキャンセルされます。

コード例を使用した関連記事:

ExecutorServiceの送信とExecutorServiceの実行の選択

16
Ravindra babu

Submit-送信されたタスクの結果を確認するために使用できるFutureオブジェクトを返します。 isDoneなどのキャンセルまたはチェックに使用できます。

実行-何も返しません。

5
Preetham R U

Submit()メソッドとexecute()メソッドの主な違いは、ExecuterService.submit()はFutureの戻り値型を持っているため、計算結果を返すことができますが、execute()メソッドは戻り値の型がvoidであるため何も返すことができないことです。 Java 1.5のExecutorフレームワークのコアインターフェイスは、execute(Runnable task)メソッドを定義するExecutorインターフェイスです。その主な目的は、タスクを実行から分離することです。

Executorに送信されたタスクは、同じスレッド、スレッドプールのワーカースレッド、または他のスレッドによって実行できます。

一方、submit()メソッドは、ExecutorのサブインターフェースであるExecutorServiceインターフェースで定義され、呼び出し可能タスクを受け入れて結果を返すsubmit()メソッドを追加するとともに、スレッドプールを終了する機能を追加します。計算の。

execute()とsubmit()の類似点:

  1. Submit()メソッドとexecute()メソッドの両方を使用して、非同期実行のためにタスクをExecutorフレームワークに送信します。
  2. Submit()とexecute()の両方がRunnableタスクを受け入れることができます。
  3. Execute()メソッドを宣言するExecutorインターフェースも拡張するため、ExecutorServiceインターフェースからsubmit()およびexecute()にアクセスできます。

submit()メソッドは出力を返すことができ、execute()は返せないという事実とは別に、Java 5。 =

  1. Submit()はRunnableタスクとCallableタスクの両方を受け入れることができますが、execute()はRunnableタスクのみを受け入れることができます。
  2. Submit()メソッドはExecutorServiceインターフェイスで宣言され、execute()メソッドはExecutorインターフェイスで宣言されます。
  3. Submit()メソッドの戻り値の型はFutureオブジェクトですが、execute()メソッドの戻り値の型はvoidです。
2
amitkumar12788

ソースコードを確認すると、submitexecuteの一種のラッパーであることがわかります。

public Future<?> submit(Runnable task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<Void> ftask = newTaskFor(task, null);
    execute(ftask);
    return ftask;
}
1
Koray Tugay

基本的に両方の呼び出しが実行され、将来のオブジェクトが必要な場合は、docからsubmit()メソッドをここで呼び出します

_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, result);
    execute(ftask);
    return ftask;
}
_

ご覧のとおり、Javaは実際にrun()メソッドを呼び出す以外にスレッドを開始する方法がありません。IMO。Callable.call()メソッドがrun() method。したがって、オブジェクトが呼び出し可能な場合、run()メソッドが呼び出され、次にdocからcall()メソッドが呼び出されます。

_public void run() {
    if (state != NEW ||
        !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                     null, Thread.currentThread()))
        return;
    try {
        Callable<V> c = callable;
        if (c != null && state == NEW) {
            V result;
            boolean ran;
            try {
                result = c.call();
                ran = true;
            } catch (Throwable ex) {
                result = null;
                ran = false;
                setException(ex);
            }
            if (ran)
                set(result);
        }
    } finally {
        // runner must be non-null until state is settled to
        // prevent concurrent calls to run()
        runner = null;
        // state must be re-read after nulling runner to prevent
        // leaked interrupts
        int s = state;
        if (s >= INTERRUPTING)
            handlePossibleCancellationInterrupt(s);
    }
}
_
0
amarnath harish