Программирование >>  Разработка устойчивых систем 

1 ... 171 172 173 [ 174 ] 175 176 177 ... 196


Приостановка

Другая операция, часто встречающаяся при управлении программными потоками, - их приостановка на заданное число миллисекунд функцией sleep(). Если в предыдущем примере заменить вызов yield() вызовом sleep(), программа принимает следующий вид:

: СИ:SleepingTask.срр

Приостановка программного потока функцией sleepO.

: Cll:Yield1ngTask.cpp

Вызов yIeldO определяет рекомендуемую

точку переключения потоков

{L} ZThread

#include <iostream>

#1nclude zthread/Thread.h

#1nclude zthread/ThreadedExecutor.h

using namespace ZThread:

using namespace std:

class YieldingTask : public Runnable {

int countDown:

int id: public:

YieldingTask(int ident = 0) : countDown(5), id(ident) {} -YieldingTaskO { cout id completed endl:

friend ostream&

operator (ostream& os. const YieldingTask& yt) { return OS # yt.id : yt.countDown:

void runO { while(true) { cout *this endl: if(--countDown == 0) return: Thread::yield():

int mainO { try {

ThreadedExecutor executor: for(int i =0: i < 5: i++) executor.execute(new Yi eldi ngTask(i)): } catch(Synchronization Exception& e) { cerr e.whatO endl:

} /:-

Как видите, функция run() объекта задачи представляет собой бесконечный цикл. При вызове y1eld() вывод программы становится более равномерным, чем без него. Попробуйте закомментировать вызов Thread::yield() и проанализируйте результат. Впрочем, на практике функция yield() применяется крайне редко, и не стоит рассчитывать, что она сможет существенно повысить эффективность работы ващего приложения.



{L} ZThread

linclude <iostream>

linclude zthread/Thread.h

Ii nclude zthread/ThreadedExecutor.h

using namespace ZThread:

using namespace std:

class SleepingTask : public Runnable {

int countDown:

int id: public:

SleepingTask(int ident = 0) : countDown(5), id(ident) {} -SleepingTaskО { cout id completed endl:

friend ostreamS

operator (ostreamS os. const SleepingTaskS st) { return OS I St.id : st.countDown:

void runO { while(true) { try {

cout *this endl: if(--countDown == 0) return: Thread::sleep(100): } catch(Interrupted ExceptionS e) { cerr e.what О endl:

int mainO { try {

ThreadedExecutor executor: fordnt i = 0: i < 5: i++) executor.execute(new SIeepingTask(i)): } catch(Synchronization ExceptionS e) { cerr e.whatO endl:

} III:-

Функция Thread::sleep() может запустить исключение Interrupted Exception (прерывания рассматриваются далее); это исключение перехватывается в run(). Но если задача создается и выполняется в блоке try функции main(), перехватывающем объекты Synchronization Exception (базовый класс для всех исключений ZThreads), нельзя ли просто игнорировать исключение в run(), предположив, что оно перейдет в обработчик mainQ? Такое рещение не работает, потому что исключения не возвращаются в main() через программные потоки. Следовательно, все возникающие исключения должны обрабатываться локально внутри задачи.

В общем случае порядок выполнения потоков непредсказуем, а это означает, что функция sleepO не может применяться для управления порядком их выполнения. Она просто приостанавливает выполнение потока на некоторое время. Гарантируется только то, что пауза продлится не менее 100 миллисекунд (в нащем примере), но может продолжаться и больще, потому что планировщик потоков должен еще добраться до приостановленного потока после истечения интервала. Для



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

Приоритеты

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

Здесь приведена измененная версия программы MoreBasicThreads.cpp, демонстрирующая работу системы приоритетов. Значения приоритетов регулируются функцией setPriorityO класса Thread:

: Cll:SimplePriorities.cpp

Приоритеты программных потоков.

{L} ZThread

#1 ncl ude <1ostream>

linclude zthread/Thread.h

using namespace ZThread:

using namespace std:

const double pi = 3.1415926538979323846: const double e = 2.7182818284590452354:

class SimplePriorities : public Runnable { int countDown:

volatile double d: Без оптимизации int id: public:

SimplePrioritiesCint ident = 0): countDown(5).id(ident){} -SimplePrioritiesO throwO { cout id completed endl:

friend ostream&

operator (ostream& os. const SimplePriorities& sp) { return OS I sp.id priority: ThreadO.getPriorityO count: sp.countDown;

void runO { while(true) {

Дорогостоящая операция, которая может прерываться; for(int i = 1; i < 100000; i++)

d = d + (M PI + M E) / (double)i: cout *this endl; if(--countDown == 0) return;

int mainO {



1 ... 171 172 173 [ 174 ] 175 176 177 ... 196

© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика