Java-исполнитель с упреждающей очередью потока - PullRequest
1 голос
/ 22 июля 2010

Я ищу пул потоков Java, который не будет запускать больше потоков одновременно, чем есть ядра в системе. Этот сервис обычно предоставляется ThreadPoolExecutor с использованием BlockingQueue.

Однако, если запланирован запуск нового потока, я хочу, чтобы новый поток опередил один из уже запущенных потоков, и добавил предварительно опущенный поток (в состоянии ожидания) в очередь задач, поэтому его можно возобновить, как только закончится новый поток.

Есть предложения?

Ответы [ 2 ]

4 голосов
/ 22 июля 2010

Я бы сделал подкласс ThreadPoolExecutor.

Когда вы устанавливаете ThreadPoolExecutor, вы хотите установить corePoolSize и maximumPoolSize на Runtime.getRuntime().availableProcessors() (посмотрите на Executors.newFixedThreadPool(), чтобы понять, почему это работает).

Далее вы хотите убедиться, что ваш Queue также реализует Deque. LinkedBlockingDeque является примером, но вы должны присмотреться к нему, чтобы посмотреть, какой из них будет работать лучше для вас. Deque позволяет вам получить стек, подобный поведению LIFO, и это именно то, что вам нужно.

Поскольку все (submit(), invokeAll()) проходит через execute(), вы захотите переопределить этот метод. В основном делайте то, что вы описали выше:

Проверьте, все ли потоки запущены. Если нет, просто запустите новый runnable в доступном потоке. Если все потоки уже запущены, вам нужно найти тот, на котором выполняется самый старый исполняемый объект, остановить его, повторно поместить в очередь где-нибудь (возможно, в начале?), А затем запустить новый работающий.

1 голос
/ 23 июля 2010

Идея ThreadPoolExecutor состоит в том, чтобы избежать всех дорогостоящих действий, связанных с созданием и уничтожением потока.Если вы абсолютно настаиваете на вытеснении запущенных задач, вы не получите этого из API по умолчанию.

Если вы хотите разрешить выполнение запущенных задач, а вместо этого только выгрузить задачи, которые не начали выполнениезатем вы можете использовать реализацию BlockingQueue, которая работает как стек (LIFO).

У вас также могут быть задачи, «опережающие» другие задачи, используя разных исполнителей с разными приоритетами потоков.По сути, если ОС поддерживает квантование по времени, то исполнитель с более высоким приоритетом получает интервал времени.

В противном случае вам нужна пользовательская реализация, которая управляет выполнением.Вы могли бы использовать SynchronousQueue и иметь ожидающие P рабочие потоки.Если клиент вызывает execute и SynchronousQueue.offer завершается неудачно, вам нужно будет создать специальный рабочий поток, который захватывает один из других потоков и отмечает их для остановки перед выполнением, и снова отмечает их возобновление после выполнения.

...