10

長期的なタスクを実行すると、最初のタスクが完了していない場合、Executor は新しいスレッドを開始しません。誰かが理由を理解し、これを修正する方法を教えてください。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.junit.Test;

public class TestExecutor {

    @Test
    public void test() throws InterruptedException {
        ExecutorService checkTasksExecutorService = new ThreadPoolExecutor(1, 10,
                100000, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>());

        for (int i = 0; i < 20; i++) {
            checkTasksExecutorService.execute(new Runnable() {

                public  void run(){
                    try {
                        System.out.println(Thread.currentThread().getName() + "   running!");
                        Thread.sleep(10000);
                    } catch (Exception e) {
                    }

                }
            });
        }

        Thread.sleep(1000000);
    }
}
4

3 に答える 3

7

これはドキュメントによって解決されます:

method で新しいタスクが送信され、実行中のスレッドexecute(java.lang.Runnable)数が より少ないcorePoolSize場合、他のワーカー スレッドがアイドル状態であっても、要求を処理するために新しいスレッドが作成されます。実行中のスレッドがそれより多いcorePoolSizeが少ない場合、キューがいっぱいの場合にのみmaximumPoolSize新しいスレッドが作成されます。

したがって、必要な動作を実現するには、次のように、を増やすかcorePoolSize、エグゼキュータ サービスに拡張不可能なキューを与えます。

ExecutorService checkTasksExecutorService = new ThreadPoolExecutor(1, 20,
    100000, TimeUnit.MILLISECONDS,
    new SynchronousQueue<Runnable>());
于 2013-07-27T15:01:33.237 に答える
4

のjavadocはExecutorService.execute()言う:

将来のある時点で指定されたコマンドを実行します。コマンドは、Executor 実装の裁量で、新しいスレッド、プールされたスレッド、または呼び出し元のスレッドで実行できます。

ThreadPoolExecutor.execute()これは、次のように述べているの javadoc によって補強されています。

タスクは、新しいスレッドまたは既存のスレッドで実行できます。

しかし、その理由はソースコメントで説明されてThreadPoolExecutor.execute()います。

タスクを正常にキューに入れることができれば、完了です

そして少し後に

タスクをキューに入れることができない場合は、新しいスレッドを追加しようとします

キューは無制限であるため、さらにタスクをキューに入れることができるため、次のタスクを実行するための新しいスレッドは作成されません。

タスクをキューに入れることができない場合にのみ、追加のスレッドが作成されます。

于 2013-07-27T15:00:00.170 に答える
4

この動作は、キューへのタスクの提供に失敗した場合に新しいスレッドが追加される ThreadPoolExecutor 内のロジックによるものです。キューは制限されていないため、事実上、コア プール サイズを超えて最大プール サイズまで大きくなることはありません。

この例を試して違いを確認してください。

   ExecutorService checkTasksExecutorService = new ThreadPoolExecutor(1, 10,
                100000, TimeUnit.MILLISECONDS,
                new SynchronousQueue<Runnable>());

        for (int i = 0; i < 10; i++) {
            checkTasksExecutorService.execute(new Runnable() {

                public void run() {
                    try {
                        System.out.println(Thread.currentThread().getName() + "   running!");
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                }
            });
        }

        //Thread.sleep(1000000); //instead this use following

//stop accepting new tasks
        checkTasksExecutorService.shutdown();

while (!checkTasksExecutorService.isTerminated()) {
            Thread.sleep(100);
        }
于 2013-07-27T14:56:17.867 に答える