Что большая часть эффективного способа ЦП состоит в том, чтобы заставить рабочие потоки ожидать задач?

В моем текущем приложении 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%, но я не совсем уверен, является ли это лучшим методом. Можно ли предложить, чтобы лучший метод сохранил потоки неактивными, не повреждая использование ЦП?

5
задан Hemant 14 January 2010 в 06:51
поделиться

4 ответа

Два параметра:

Запустите приложение Java со stdout, перенаправленным

java com.example.MyApp > out.txt

Вместо этого используйте jstack .

Утилита jstack позволяет получить дамп потока и отправить вывод на текущую консоль вместо stdout приложения Java, позволяя перенаправить его.

Например, если PID приложения Java 12345 (используйте утилиту jps для быстрого поиска):

jstack 12345 > threads.txt
-121--2392144-

Я исправил его, связав кнопку «Вставить» в главном меню NSMenu с командой первого ответчика paste: .

-121--2283217-

Проверьте эту реализацию очереди . Если очередь пуста, она использует Monitor.Wait () для перевода потока в спящий режим. При добавлении предмета он использует Monitor.Pulse () для пробуждения потока, находящегося в режиме ожидания в пустой очереди.

Другой метод заключается в использовании семафора . При каждом добавлении предмета в очередь вызовите функцию Release (). Если требуется предмет из очереди, вызовите WaitOne ().

7
ответ дан 14 December 2019 в 01:08
поделиться

есть пару вариантов, о которых я могу думать.

Один из способов - поместить небольшую нить спать во время цикла. Это в основном упадет вашему процессору для 0 и довольно стандартный способ сделать это.

Другим способом является использование сброса (AUTO или MANAL), что предложено Митческую пшеницу в комментариях.

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

0
ответ дан 14 December 2019 в 01:08
поделиться

В настоящее время в вашем методе работы есть Thread.Sleep(0) для тех случаев, когда нет очереди элементов. Измените его на что-нибудь больше 0 и использование процессора снизится. Попробуйте 10, чтобы начать с...

2
ответ дан 14 December 2019 в 01:08
поделиться

Если ваша очередь безопасна для нитей, то вам не нужно будет этого делать...

    //Someone else might have been lucky in stealing 
    //the task by the time we dequeued it!! 
    if (task == null)  
        continue; 
0
ответ дан 14 December 2019 в 01:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: