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

This is settled by the documentation:

When a new task is submitted in method execute(java.lang.Runnable), and fewer than corePoolSize threads are running, a new thread is created to handle the request, even if other worker threads are idle. If there are more than corePoolSize but less than maximumPoolSize threads running, a new thread will be created only if the queue is full.

So, to achieve the behavior you want, either increase the corePoolSize or give the executor service a non-growable queue, like this:

ExecutorService checkTasksExecutorService = new ThreadPoolExecutor(1, 20,
    100000, TimeUnit.MILLISECONDS,
    new SynchronousQueue<Runnable>());
于 2013-07-27T15:01:33.237 回答
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 回答
4

的 javadocExecutorService.execute()说:

在将来的某个时间执行给定的命令。该命令可以在新线程、池线程或调用线程中执行,由 Executor 实现自行决定

This is reinforced by the javadoc for ThreadPoolExecutor.execute(), which says:

The task may execute in a new thread or in an existing thread.

But the reason is explained in the source comments for ThreadPoolExecutor.execute() which says:

If a task can be successfully queued, then we are done

and a bit later

If we cannot queue the task, then we try to add a new thread

Since your queue is unbounded, further tasks can be queued, so new threads are not created to execute the following tasks.

More threads are created only if the task can not be queued.

于 2013-07-27T15:00:00.170 回答