В моем текущем приложении C#/NET 3.5 у меня есть (ориентированная на многопотоковое исполнение) очередь задачи, и у меня есть 5 рабочих потоков, который должен постоянно искать задачи в очереди. Если задача будет доступна, то любой рабочий исключит задачу из очереди и примет требуемые меры.
Мой класс рабочего потока следующие:
public class WorkerThread
{
//ConcurrentQueue is my implementation of thread safe queue
//Essentially just a wrapper around Queue<T> with synchronization locks
readonly ConcurrentQueue<CheckPrimeTask> mQ;
readonly Thread mWorker;
bool mStop;
public WorkerThread (ConcurrentQueue<CheckPrimeTask> aQ) {
mQ = aQ;
mWorker = new Thread (Work) {IsBackground = true};
mStop = false;
}
private void Work () {
while (!mStop) {
if (mQ.Count == 0) {
Thread.Sleep (0);
continue;
}
var task = mQ.Dequeue ();
//Someone else might have been lucky in stealing
//the task by the time we dequeued it!!
if (task == null)
continue;
task.IsPrime = IsPrime (task.Number);
task.ExecutedBy = Thread.CurrentThread.ManagedThreadId;
//Ask the threadpool to execute the task callback to
//notify completion
ThreadPool.QueueUserWorkItem (task.CallBack, task);
}
}
private bool IsPrime (int number) {
int limit = Convert.ToInt32 (Math.Sqrt (number));
for (int i = 2; i <= limit; i++) {
if (number % i == 0)
return false;
}
return true;
}
public void Start () {
mStop = false;
mWorker.Start ();
}
public void Stop () {
mStop = true;
}
}
Проблема состоит в том, что, когда очередь пуста, она использует слишком много ЦП (почти 98%). Я попробовал AutoResetEvent, чтобы уведомить рабочих, что очередь была изменена. Таким образом, они эффективно ожидают того сигнала установить. Это принесло вниз ЦП почти к 0%, но я не совсем уверен, является ли это лучшим методом. Можно ли предложить, чтобы лучший метод сохранил потоки неактивными, не повреждая использование ЦП?
Два параметра:
Запустите приложение Java со stdout, перенаправленным
java com.example.MyApp > out.txt
Вместо этого используйте jstack
.
Утилита jstack позволяет получить дамп потока и отправить вывод на текущую консоль вместо stdout приложения Java, позволяя перенаправить его.
Например, если PID приложения Java 12345 (используйте утилиту jps для быстрого поиска):
jstack 12345 > threads.txt
-121--2392144- Я исправил его, связав кнопку «Вставить» в главном меню NSMenu с командой первого ответчика paste:
.
Проверьте эту реализацию очереди . Если очередь пуста, она использует Monitor.Wait () для перевода потока в спящий режим. При добавлении предмета он использует Monitor.Pulse () для пробуждения потока, находящегося в режиме ожидания в пустой очереди.
Другой метод заключается в использовании семафора . При каждом добавлении предмета в очередь вызовите функцию Release (). Если требуется предмет из очереди, вызовите WaitOne ().
есть пару вариантов, о которых я могу думать.
Один из способов - поместить небольшую нить спать во время цикла. Это в основном упадет вашему процессору для 0 и довольно стандартный способ сделать это.
Другим способом является использование сброса (AUTO или MANAL), что предложено Митческую пшеницу в комментариях.
Вы также можете разработать какую-то рубашку, которая имеет резьб спать в течение определенного количества времени, и если ваша очередь пуста, просто обрабатывайте рубежом (которая будет нить спать).
В настоящее время в вашем методе работы есть Thread.Sleep(0)
для тех случаев, когда нет очереди элементов. Измените его на что-нибудь больше 0 и использование процессора снизится. Попробуйте 10
, чтобы начать с...
Если ваша очередь безопасна для нитей, то вам не нужно будет этого делать...
//Someone else might have been lucky in stealing
//the task by the time we dequeued it!!
if (task == null)
continue;