2010-07-22 3 views
1

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

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

Любые предложения?

+0

Я думаю, что Java-Threads не должны использоваться так, поскольку нет возможности временно остановить, а затем продолжить поток, за исключением случаев, когда вы реализуете такой метод самостоятельно. Но нет общего способа предустановить выполнение, приостановить выполнение и продолжить другой поток. На самом деле, в вашей системе никогда больше нет потоков * работает *, чем количество ядер в вашей системе. Это простой закон физики. Если вы используете больше потоков, чем количество ядер в вашей системе, java автоматически планирует доступные процессоры среди запущенных потоков (с использованием pre-emption). – Javaguru

+0

Спасибо за ваш ответ. Я знаю, что потоковая подвеска устарела в java, однако существуют альтернативные методы, описанные здесь: http://download.oracle.com/docs/cd/E17476_01/javase/1.4.2/docs/guide /misc/threadPrimitiveDeprecation.html. Я применил аналогичный метод для приостановки моих потоков. Моя цель - как можно скорее завершить «новые» задачи. – TinkerTank

ответ

4

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

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

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

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

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

1

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

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

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

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

Смежные вопросы