Как сохранить живость основных потоков и избавиться от лишних потоков в ThreadPoolExecutor?keepAliveTime не работает должным образом - PullRequest
2 голосов
/ 05 января 2012

Я использую ThreadPoolExecutor для управления пулом потоков. Что мы хотим:

  1. если в пуле меньше потоков corePoolSize, запустить новый поток для новой задачи;
  2. если в пуле больше потоков corePoolSize, и все они заняты, запускайте новый поток для новой задачи, пока не будет достигнут maxPoolSize. В этом случае отклоните задачу;
  3. поддержание количества потоков corePoolSize в активном состоянии, даже если они простаивают, лишние потоки умрут, если они простаивают более, чем keepAliveTime

Согласно документации по Java6, keepAliveTime должен работать, как указано выше. Но в моем тестовом коде он не работает согласованно.

Когда я устанавливаю keepAliveTime в 0, он работает нормально, всегда поддерживая основные потоки живыми и заканчивая избыточные потоки, когда они заканчивают;
но, как показано ниже, когда я устанавливаю keepAliveTime в положительное значение, создается впечатление, что он прерывает ВСЕ незанятые потоки, независимо от того, являются они основными или нет.

ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 500, TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>());
assertFalse("Not allow core threads to time out.", executor.allowsCoreThreadTimeOut());
Task task_1 = new Task(1000);
Task task_2 = new Task(1000);
Task task_3 = new Task(1000);
executor.execute(task_1);
executor.execute(task_2);
executor.execute(task_3);
Thread.sleep(1050L);
assertEquals("Completed 3 tasks.", 3, executor.getCompletedTaskCount());
assertEquals("Three threads are in the pool.", 3, executor.getPoolSize());
Thread.sleep(600L);
//////// This assertion will fail: **expected <2> but was <0>**
assertEquals("Two threads are in the pool.", 2, executor.getPoolSize());

////----
private static class Task implements Runnable {
    private long sleepMillis;
    public Task(final long sleepMillis) {
        this.sleepMillis = sleepMillis;
    }
    public void run() {
        try { Thread.sleep(sleepMillis);
        } catch (Exception e) { System.out.println(e); }
    }
}

Есть ли недопонимание по поводу keepAliveTime или getPoolSize? Если getPoolSize не является правильным API, как я могу узнать количество «живых» потоков (свободных или занятых)?

Заранее спасибо.

Ответы [ 3 ]

1 голос
/ 05 января 2012

Java 7 проходит тест.По-видимому, в Java 6 есть ошибка.Считая его код, все потоки могут выйти, когда очередь пуста, что явно не подходит для основных потоков.

1 голос
/ 05 июня 2017

@ arosima keepAliveTime действует только на избыточные потоки, а не на основные потоки.Основные потоки всегда будут храниться в пуле.Я также написал другой ответ , чтобы понять, надеюсь, это полезно.

0 голосов
/ 05 января 2012

Я почти уверен, что размер пула является целевым.Я не думаю, что есть какие-либо гарантии по закрытию потоков (нет проверки фона), я думаю, это просто подсказка.Свободные потоки дают почти никаких издержек.

...