|
Программирование >> Разработка устойчивых систем
таксис. Хотя многопоточность по-прежнему остается достаточно сложной темой, программисты Java начинают осваивать и применять ее на относительно ранней стадии. Комитет по стандартизации С++ рассматривает вопрос о включении поддержки многопоточности в следующую версию стандарта С++, но на момент написания книги остается неясным, как все это будет выглядеть. В качестве основы при подготовке этой главы была выбрана библиотека ZThreads, причем помощь авторам оказывал разработчик библиотеки, Эрик Крэхен (Eric Crahen) из IBM. Библиотека ZThreads хорошо спроектирована и свободно распространяется с открытыми текстами по адресу http: zthread.sourceforge.net. Для демонстрации основных принципов многопоточности мы будем использовать лишь часть возможностей ZThreads. На самом деле библиотека обладает гораздо более совершенной поддержкой многопоточности, чем показано в книге. Самостоятельное изучение позволит вам лучше разобраться в ее возможностях. Установка библиотеки ZThreads Пожалуйста, учтите, что библиотека ZThreads является независимым проектом, и к ее разработке авторы книги отношения не имеют; мы просто используем эту библиотеку и не предоставляем технической поддержки для ее установки. За информацией об установке и ошибках обращайтесь на сайт разработчика. Библиотека ZThreads распространяется на уровне исходных текстов. После ее загрузки (версии 2.3 и выше) с сайта необходимо откомпилировать библиотеку и подготовить проект к использованию библиотеки. В большинстве разновидностей Unix (Linux, SunOS, Cygwin и т. д.) компиляцию ZThreads рекомендуется производить при помощи конфигурационного сценария. После распаковки файлов утилитой tar выполните в основном каталоге архива ZThreads команду ./configure && make install Команда компилирует и устанавливает копию библиотеки в каталог /usr/local. При использовании этого сценария можно задать множество параметров, в том числе определяющих расположение файлов. Чтобы получить дополнительную информацию, выполните команду ./configure -help Код ZThreads структурирован таким образом, чтобы упростить компиляцию для других платформ и компиляторов (таких, как Borland, Microsoft и Metrowerks). Для этого следует создать новый проект и включить все схх-файлы из каталога src архива ZThreads в список компилируемых файлов. Также не забудьте включить каталог include архива в список путей к заголовочным файлам вашего проекта. Подробности зависят от конкретного компилятора, поэтому для использования этой возможности вы должны достаточно хорошо разбираться в своем инструментарии. После успешной компиляции следующим шагом является создание проекта, использующего откомпилированную библиотеку. Сначала необходимо сообщить компилятору местонахождение заголовочных файлов, чтобы ваши команды #include работали правильно. Обычно для этого в проект включается ключ вида -I/nyrt/include Определение задач Каждый программный поток решет некоторую задачу; следовательно, нам понадобятся средства для описания подобных задач. Класс Runnable определяет общий интерфейс для выполнения произвольной задачи. Ниже приведено ядро класса Runnable библиотеки ZThread, находящееся в файле Runnable.h каталога include после установки библиотеки ZThread: class Runnable { public: virtual void runO = 0: virtual void -RunnableO {} Определение Runnable в виде абстрактного базового класса позволяет легко объединять его с другими классами. Чтобы определить задачу, просто объявите ее класс производным от класса Runnable и переопределите функцию run() так, чтобы она выполняла нужные действия. Например, следующая задача LiftOff осуществляет обратный отсчет до нуля: : Cll:LiftOff.h Демонстрация интерфейса Runnable. #ifndef LIFTOFF H #define LIFTOFFJ #include zthread/Runnable.h Если вы задействовали сценарий configure, то путь определяется выбранным префиксом (по умолчанию /usr/local/). А при использовании файлов проектов из каталога build он просто соответствует пути к основному каталогу архива ZThreads. Далее в проект необходимо включить ключ, который сообщает компоновщику, где ему искать библиотеку. При использовании конфигурационного сценария этот ключ выглядит так: -L/nyrb/lib -IZThread При использовании файлов проектов он принимает вид -L/nyyb/Debug Zthread.lib Как и при определении местонахождения заголовочных файлов, если вы задействовали сценарий configure, путь определяется выбранным префиксом (по умолчанию /usr/local/). А в случае готовых файлов проектов он соответствует пути к основному каталогу архива ZThreads. Если вы используете Linux или Cygwin (www.cygwin.com) в среде Windows, возможно, изменять пути к заголовочным или библиотечным файлам не понадобится; процесс установки часто рещает эту задачу за вас. Вероятно, в системе Linux вам придется включить следующую строку в .bashrc, чтобы система времени выполнения могла находить общую библиотеку LibZThread-X.X.SO.0 при выполнении программ, приводимых в этой главе (предполагается, что вы использовали стандартный процесс установки, а общая библиотека находится в каталоге /usr/local/lib; в противном случае соответствующим образом измените путь): export LD LIBRARY PATH=/usг/1 oca1/11b:${LD LIBRARY PATH} Программные потоки Чтобы запустить объект Runnable в отдельном программном потоке, создайте объект Thread и передайте его конструктору указатель на Runnable. Тем самым обеспечивается инициализация программного потока и дальнейшее выполнение в нем функции run() класса Runnable под управлением операционной системы. Следующий пример, в котором Thread управляет работой Liftoff, показывает, как организуется запуск задачи в контексте программного потока: : Cll:BasicThreads.cpp Простейшее использование класса Thread {L} ZThread linclude <iostream> linclude LiftOff.h linclude zthread/Thread.h using namespace ZThread: linclude <iostreani> class Liftoff : public ZThread::Runnable { int countDown: int id: public: Liftoff(int count, int ident = 0) : countDown(count). id(ident) {} -LiftoffО { std::cout id completed std::endl: void runO { while(countDown--) std::cout id : countDown std::endl: std::cout Liftoff! std::endl: lendif LIFT0FF H /:- Переменная id идентифицирует разные экземпляры одной задачи. Если программа запускается в единственном экземпляре, передайте значение по умолчанию в параметре ident. Деструктор помогает убедиться в том, что объект задачи был должным образом уничтожен. В следующем примере функция гип() объекта задачи запускается не в отдельном потоке, а напрямую вызывается в main(): : Cll:NoThread.cpp linclude LiftOff.h int mainO { Liftoff launch(lO): launch. runO: } III:- Классы, производные от Runnable, должны содержать функцию run(), но эта функция не делает ничего особенного - она не обладает никакими особыми многопоточными свойствами. Многопоточное выполнение программы обеспечивается классом Thread.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |