SlideShare une entreprise Scribd logo
1  sur  27
Télécharger pour lire hors ligne
Темы лекции: Многопоточность в Qt.
Практическое задание: Многопоточность в Qt.
Тренер: Игорь Шкулипа, к.т.н.
С++ Библиотеки STL и Qt. Занятие 8
http://www.slideshare.net/IgorShkulipa 2
Object Pool
Применение паттерна Object Pool может значительно повысить
производительность системы; его использование наиболее
эффективно в ситуациях, когда создание экземпляров
некоторого класса требует больших затрат, объекты в системе
создаются часто, но число создаваемых объектов в единицу
времени ограничено.
Пулы объектов (известны также как пулы ресурсов)
используются для управления кэшированием объектов.
Клиент, имеющий доступ к пулу объектов может избежать
создания новых объектов, просто запрашивая в пуле уже
созданный экземпляр. Пул объектов может быть растущим,
когда при отсутствии свободных создаются новые объекты или
c ограничением количества создаваемых объектов.
http://www.slideshare.net/IgorShkulipa 3
Реализация Object Pool на основе Singleton. Классы
объектов
class IObject {
protected:
string _strText;
public:
virtual void Print() {
cout<<"The Object is: "<<_strText.c_str()<<"n";
} };
class Object1: public IObject {
public:
Object1(){
_strText="Object 1";
} };
class Object2: public IObject {
public:
Object2(){
_strText="Object 2";
} };
class Object3: public IObject {
public:
Object3(){
_strText="Object 3";
} };
class Object4: public IObject {
public:
Object4(){
_strText="Object 4";
} };
http://www.slideshare.net/IgorShkulipa 4
Object Pool
template<unsigned poolSize> class ObjectPool{
public:
static ObjectPool* GetInstance() {
if (!_instance) _instance=new ObjectPool();
return _instance;
}
IObject* GetObject() {
for (unsigned i=0;i<poolSize;i++)
{ if (!_busyObjects[i]){
_busyObjects[i]=true;
return _objectPool[i];
} }
return NULL;
}
void ReleaseObject(IObject* object){
for (unsigned i=0;i<poolSize;i++)
{ if (_objectPool[i]==object){
_busyObjects[i]=false;
} }
}
...
http://www.slideshare.net/IgorShkulipa 5
Object Pool
...
private:
ObjectPool(){
for (unsigned i=0;i<poolSize;i++)
{
unsigned iObjNumber=rand()%4;
switch (iObjNumber)
{
case 0: _objectPool[i]=new Object1(); break;
case 1: _objectPool[i]=new Object2(); break;
case 2: _objectPool[i]=new Object3(); break;
case 3: _objectPool[i]=new Object4(); break;
}
_busyObjects[i]=false;
}
}
private:
IObject* _objectPool[poolSize];
bool _busyObjects[poolSize];
static ObjectPool* _instance;
};
http://www.slideshare.net/IgorShkulipa 6
Использование Object Pool
template<unsigned poolSize>
ObjectPool<poolSize>* ObjectPool<poolSize>::_instance=NULL;
int main()
{
ObjectPool<5>* op=ObjectPool<5>::GetInstance();
IObject* object1=op->GetObject();
if (object1) object1->Print(); else cout<<"The Object is: NULLn";
IObject* object2=op->GetObject();
if (object2) object2->Print(); else cout<<"The Object is: NULLn";
IObject* object3=op->GetObject();
if (object3) object3->Print(); else cout<<"The Object is: NULLn";
IObject* object4=op->GetObject();
if (object4) object4->Print(); else cout<<"The Object is: NULLn";
IObject* object5=op->GetObject();
if (object5) object5->Print(); else cout<<"The Object is: NULLn";
IObject* object6=op->GetObject();
if (object6) object6->Print(); else cout<<"The Object is: NULLn";
IObject* object7=op->GetObject();
if (object7) object7->Print(); else cout<<"The Object is: NULLn";
op->ReleaseObject(object2);
IObject* object8=op->GetObject();
if (object8) object8->Print(); else cout<<"The Object is: NULLn";
}
http://www.slideshare.net/IgorShkulipa 7
Результат
The Object is: Object 2
The Object is: Object 4
The Object is: Object 3
The Object is: Object 1
The Object is: Object 2
The Object is: NULL
The Object is: NULL
The Object is: Object 4
http://www.slideshare.net/IgorShkulipa 8
Преимущества и недостатки
◦ Пул объектов отслеживает объекты, которые он создает.
◦ Паттерн Object Pool может использоваться для инкапсуляции
логики создания объектов. Однако он не управляет ими
после их создания.
◦ Достоинством этого паттерна является быстрое создание
объектов, однако это реализовано за счет использования
больших ресурсов памяти.
http://www.slideshare.net/IgorShkulipa 9
Процессы и потоки
Процессы представляют собой программы, независимые друг от друга и
загруженные для исполнения. Каждый процесс должен создавать хотя
бы один поток, называемый основным. Основной поток процесса
создается в момент запуска программы. Однако сам процесс может
создавать несколько потоков одновременно.
Многопоточность позволяет разделять задачи и независимо работать над
каждой из них для того, чтобы максимально эффективно
задействовать процессор. Написание многопоточных приложений
требует больше времени и усложняет процесс отладки, поэтому
многопоточность нужно применять тогда, когда это действительно
необходимо.
Многопоточность удобно использовать для того, чтобы блокировка или
зависание одного из методов не стали причиной нарушения
функционирования основной программы.
http://www.slideshare.net/IgorShkulipa 10
QProcess
Процесс — это экземпляр программы, загруженной в память компьютера
для выполнения.
Создание процесса может оказаться полезным для использования
функциональных возможностей программ, не имеющих графического
интерфейса и работающих с командной строкой. Другое полезное
свойство — довольно простой запуск других программ из текущей
программы.
Процессы можно создавать с помощью класса QProcess, который
определен в заголовочном файле QProcess. Благодаря тому, что этот
класс унаследован от класса QIODevice, объекты этого класса в
состоянии считывать информацию, выводимую запущенными
процессами, и даже подтверждать их запросы на ввод информации.
Этот класс содержит методы для манипулирования системными
переменными процесса.
Работа с объектами класса QProcess производится в асинхронном
режиме, что позволяет сохранять работоспособность графического
интерфейса программы в моменты, когда запущенные процессы
находятся в работе.
http://www.slideshare.net/IgorShkulipa 11
QThread
Для использования многопоточности можно унаследовать класс от QThread и
перезаписать метод run(), в который должен быть помещен код для исполнения
в потоке. Чтобы запустить поток, нужно вызвать метод start().
class CustomThread : public QThread
{
public:
CustomThread();
void setMessage(const QString &message);
void run() {/*Действия потока*/};
void stop();
private:
QString messageStr;
volatile bool stopped;
};
//...
int main(int argc, char** argv)
{
CustomThread thread;
thread.start();
}
http://www.slideshare.net/IgorShkulipa 12
Приоритет потоков
У каждого потока есть приоритет, указывающий процессору, как должно протекать
выполнение потока по отношению к другим потокам. Приоритеты разделяются
по группам:
• в первую входят четыре наиболее часто применяемых приоритета. Их
значимость распределяется по возрастанию — IdlePriority, LowestPriority,
LowPriority, NormaiPriority. Они подходят для решения задач, которым
процессор требуется только время от времени, например, для фоновой
печати или для каких-нибудь несрочных действий;
• во вторую группу входят два приоритета — HighPriority, HighestPriority.
Пользуйтесь такими приоритетами с большой осторожностью. Обычно эти
потоки большую часть времени ожидают какие-либо события;
• в третью входят два приоритета — TimeCriticalPriority, InheritPriority.
Потоки с этими приоритетами нужно создавать в случаях крайней
необходимости. Эти приоритеты нужны для программ, напрямую
общающихся с аппаратурой или выполняющих операции, которые ни в коем
случае не должны прерваться.
Для того чтобы запустить поток с нужным приоритетом, необходимо передать одно
из приведенных выше значений в метод start(). Например:
CustomThread thread;
thread.start(QThread::IdlePriority);
http://www.slideshare.net/IgorShkulipa 13
Синхронизация
Основные сложности возникают тогда, когда потокам нужно совместно
использовать одни и те же данные. Так как несколько потоков могут
одновременно обращаться и записывать данные в одну область, то это
может привести к нежелательным последствиям.
Синхронизация позволяет задавать критические секции (critical
sections), к которым в определенный момент имеет доступ только один
из потоков. Это гарантирует то, что данные ресурса, контролируемые
критической секцией, будут невидимы другими потоками и они не
изменят их. И только после того, как поток выполнит всю
необходимую работу, он освобождает ресурс, и, затем, доступ к этому
ресурсу может получить любой другой поток.
Например, если один поток записывает информацию в файл, то все
другие не смогут использовать этот файл до тех пор, пока поток не
освободит его.
http://www.slideshare.net/IgorShkulipa 14
Объекты синхронизации Mutex
Мьютексы (mutex) обеспечивают взаимоисключающий доступ к ресурсам,
гарантирующий то, что критическая секция будет обрабатываться только одним
потоком. Поток, владеющий мьютексом, обладает эксклюзивным правом на
использование ресурса, защищенного мьютексом, и другой поток не может
завладеть уже занятым мьютексом.
Механизм мьютексов реализован классом QMutex. Метод lock() класса QMutex
производит блокировку ресурса. Для обратной операции существует метод
unlock(), который открывает закрытый ресурс для других потоков.
Класс QMutex также содержит метод tryLock(). Этот метод можно использовать для
того, чтобы проверить, заблокирован ресурс или нет. Этот метод не
приостанавливает исполнение потока и возвращается немедленно, со значением
false, если ресурс уже захвачен другим потоком, и не ожидает его
освобождения. В случае успешного захвата ресурса этот метод вернет true.
В сложных функциях, особенно при использовании исключений C++, легко можно
ошибиться при выполнении последовательностей операций по
запиранию/отпиранию мьютексов. Поэтому, в состав Qt включен класс
QMutexLocker, который значительно упрощает работу с мьютексами.
Конструктор класса QMutexLocker принимает объект QMutex в виде
аргумента и запирает его. Деструктор класса QMutexLocker - отпирает
мьютекс.
http://www.slideshare.net/IgorShkulipa 15
Пример «Потокобезопасный стек»
template <class Type>
class ThreadSafeStack
{
public:
void push(const Type& val)
{
mutex.lock();
stack.push(val);
mutex.unlock();
}
Type pop()
{
QMutexLocker locker (&mutex);
return stack.empty() ? Type() : stack.pop();
}
private:
QMutex mutex;
QStack<Type> stack;
};
http://www.slideshare.net/IgorShkulipa 16
QWaitCondition
Библиотека Qt предоставляет класс QWaitCondition, обеспечивающий
возможность координации потоков.
Если поток намеревается дождаться разблокировки ресурса, то он
вызывает метод QWaitCondition::wait() и, тем самым, входит в
режим ожидания. Выводится он из этого режима в том случае, если
поток, который заблокировал ресурс, вызовет метод
QWaitCondition::wakeOne() или QWaitCondition::wakeAll().
Разница этих двух методов в том, что первый выводит из состояния
ожидания только один поток, а второй — все сразу. Также для потока
можно установить время, в течение которого он может ожидать
разблокировки данных. Для этого нужно передать в метод wait()
целочисленное значение, обозначающее временной интервал в
миллисекундах.
http://www.slideshare.net/IgorShkulipa 17
Семафоры
Семафоры являются обобщением мьютексов. Как и мьютексы, они
служат для защиты критических секций, чтобы доступ к ним
одновременно могло иметь определенное число потоков. Все другие
потоки обязаны ждать.
Предположим, что программа поддерживает пять ресурсов одного и того
же типа, одновременный доступ к которым может быть предоставлен
только пяти потокам. Как только все пять ресурсов будут
заблокированы, следующий поток, запрашивающий ресурс данного
типа, будет приостановлен до освобождения одного из них.
Принцип действия семафоров очень прост. Они начинают действовать с
установленного значения счетчика. Каждый раз, когда поток получает
право на владение ресурсом, значение этого счетчика уменьшается на
единицу. И наоборот, когда поток уступает право владения этим
ресурсом, счетчик увеличивается на единицу. При значении счетчика
равном нулю семафор становится недоступным. Механизм семафоров
реализует класс QSemaphore. Счетчик устанавливается в
конструкторе при создании объекта этого класса.
http://www.slideshare.net/IgorShkulipa 18
Взаимная блокировка
При работе с многопоточностью, возможна
такая ситуация, когда поток
заблокировал ресурс А, а после
работы над ним собирается работать с
ресурсом В. Другой же поток
заблокировал ресурс В и по окончании
намеревается работать с ресурсом А. И
вот один из потоков, закончив работу,
обнаружил, что нужный ему ресурс
заблокирован другим потоком. Он
переходит в режим ожидания, надеясь
дождаться разблокировки ресурса, но
то же самое делает и другой поток.
В итоге — оба ждут друг друга. Если ни один из этих потоков не освободит занятый
им ресурс, то оба "зависнут" и не смогут продолжать свою работу дальше.
Это явление получило название взаимной блокировки (deadlock).
Существует множество решений такой проблемы. Например, можно так организовать
работу потока, чтобы, в том случае, если поток не сможет получить доступ к
необходимому ресурсу, он просто произвел бы освобождение занятых им
ресурсов, а позже повторил попытку захвата необходимых ресурсов.
http://www.slideshare.net/IgorShkulipa 19
Обмен сообщениями между потоками
Один из важнейших вопросов при многопоточном программировании —
это обмен сообщениями.
Каждый поток может иметь свой собственный цикл событий. Благодаря
этому можно осуществлять связь между объектами. Такая связь может
производиться двумя способами: при помощи соединения сигналов и
слотов или обмена событиями.
Класс QObject реализован так, что обладает близостью к потокам.
Каждый объект, произведенный от унаследованного от QObject
класса, располагает ссылкой на поток, в котором он был создан. Эту
ссылку можно получить вызовом метода QObject::thread(). Потоки
осведомляют свои объекты. Благодаря этому каждый объект знает, к
какому потоку он принадлежит.
Обработка событий производится из контекста принадлежности объекта к
потоку, то есть обработка его событий будет производиться в том
потоке, которому объект принадлежит. Объекты можно перемещать из
одного потока в другой с помощью метода
QObject::moveToThread().
http://www.slideshare.net/IgorShkulipa 20
Отправка событий
Отправка событий — это еще одна из возможностей для осуществления
связи между объектами. Есть два метода для высылки событий -
QCoreApplication::postEvent() и QCoreApplication::sendEvent().
Для того чтобы объект потока был в состоянии обрабатывать получаемые
события, в классе потока нужно реализовать метод QObject::event().
Если поток предназначен исключительно для отправки событий, а не для
их получения, то реализацию методов обработки событий и запуск
цикла обработки событий можно опустить.
http://www.slideshare.net/IgorShkulipa 21
Сигналы и слоты
Можно взять сигнал объекта одного потока и соединить его со слотом
объекта другого потока. Как мы уже знаем, соединение с помощью
метода connect() предоставляет дополнительный параметр,
обозначающий режим обработки и равный, по умолчанию, значению
Qt::AutoConnection, которое соответствует автоматическому режиму.
Как только происходит высылка сигнала, Qt проверяет — происходит
связь в одном и том же или разных потоках. Если это один и тот же
поток, то высылка сигнала приведет к прямому вызову метода. В том
случае, если это разные потоки, сигнал будет преобразован в событие
и доставлен нужному объекту.
Сигналы и слоты в Qt реализованы с механизмом надежности работы в
потоках, а это означает, что вы можете высылать сигналы и получать,
не заботясь о блокировке ресурсов.
http://www.slideshare.net/IgorShkulipa 22
Пример «Спам-бот». См. Занятие №8.
#ifndef SPAMBOT_H
#define SPAMBOT_H
#include <QObject>
#include <QString>
#include <QTime>
#include "chatmessage.h"
class SpamBot: public QObject
{
Q_OBJECT
public:
SpamBot();
void stop();
void run();
public slots:
void handleRun();
signals:
void sendSpam();
private:
volatile bool stopped;
};
#endif // SPAMBOT_H
http://www.slideshare.net/IgorShkulipa 23
Реализация класса
#include "spambot.h"
SpamBot::SpamBot() {
stopped=false;
}
void SpamBot::stop() {
stopped=true;
}
void SpamBot::run() {
while(!stopped)
{
QTime endTime= QTime::currentTime().addSecs(3);
while( QTime::currentTime() < endTime )
{
//Waiting...
}
emit sendSpam();
}
}
void SpamBot::handleRun() {
this->run();
}
http://www.slideshare.net/IgorShkulipa 24
Дополненный презентер
class ChatClientPresenter: public QObject
{
Q_OBJECT
public:
ChatClientPresenter(ChatClient* cl, IView* v);
ChatClientPresenter(IView* v);
void emitRunBot()
{
emit runBot();
}
signals:
void runBot();
private slots:
void DisplayMessage();
void SendMessage();
void SendMessageSpam();
private:
ChatClient* client;
IView* view;
};
void ChatClientPresenter::SendMessageSpam()
{
ChatMessage message("SpamBot","Spam");
client->sendToServer(message);
}
http://www.slideshare.net/IgorShkulipa 25
Функция main
#include <QtGui/QApplication>
#include "mainwindow.h"
#include "chatclientpresenter.h"
#include "spambot.h"
#include <QThread>
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
MainWindow* view=new MainWindow();
ChatClientPresenter* present=new ChatClientPresenter(view);
view->show();
QThread *thread=new QThread();
SpamBot *spamBot=new SpamBot();
QObject::connect(spamBot, SIGNAL(sendSpam()),
present,SLOT(SendMessageSpam()),Qt::QueuedConnection);
QObject::connect(present, SIGNAL(runBot()),
spamBot, SLOT(handleRun()), Qt::QueuedConnection);
spamBot->moveToThread(thread);
thread->start();
present->emitRunBot();
return a.exec();
}
http://www.slideshare.net/IgorShkulipa 26
Результат
http://www.slideshare.net/IgorShkulipa 27
Лабораторная работа №8. Многопоточность
Создать в тетрисе дополнительный поток, который с определенной
периодичностью будет обновлять рейтинг пользователей на форме
(см. Лабораторную работу №5).

Contenu connexe

Tendances

Tendances (20)

C++ STL & Qt. Занятие 06.
C++ STL & Qt. Занятие 06.C++ STL & Qt. Занятие 06.
C++ STL & Qt. Занятие 06.
 
C++ STL & Qt. Занятие 09.
C++ STL & Qt. Занятие 09.C++ STL & Qt. Занятие 09.
C++ STL & Qt. Занятие 09.
 
Java Core. Lecture# 5. Concurrency.
Java Core. Lecture# 5. Concurrency.Java Core. Lecture# 5. Concurrency.
Java Core. Lecture# 5. Concurrency.
 
Java Core. Lecture# 3. Part# 3. Multithreading.
Java Core. Lecture# 3. Part# 3. Multithreading.Java Core. Lecture# 3. Part# 3. Multithreading.
Java Core. Lecture# 3. Part# 3. Multithreading.
 
Java. Многопоточность.
Java. Многопоточность.Java. Многопоточность.
Java. Многопоточность.
 
Java осень 2014 занятие 3
Java осень 2014 занятие 3Java осень 2014 занятие 3
Java осень 2014 занятие 3
 
Java осень 2014 занятие 5
Java осень 2014 занятие 5Java осень 2014 занятие 5
Java осень 2014 занятие 5
 
Java осень 2014 занятие 6
Java осень 2014 занятие 6Java осень 2014 занятие 6
Java осень 2014 занятие 6
 
Java Core. Lecture# 3. Part# 2. Exceptions.
Java Core. Lecture# 3. Part# 2. Exceptions.Java Core. Lecture# 3. Part# 2. Exceptions.
Java Core. Lecture# 3. Part# 2. Exceptions.
 
Ввведение в java
Ввведение в javaВвведение в java
Ввведение в java
 
Java Core. Lecture# 1. Intro
Java Core. Lecture# 1. IntroJava Core. Lecture# 1. Intro
Java Core. Lecture# 1. Intro
 
Введение в сетевые технологии
Введение в сетевые технологииВведение в сетевые технологии
Введение в сетевые технологии
 
C# Desktop. Занятие 01.
C# Desktop. Занятие 01.C# Desktop. Занятие 01.
C# Desktop. Занятие 01.
 
C# Desktop. Занятие 02.
C# Desktop. Занятие 02.C# Desktop. Занятие 02.
C# Desktop. Занятие 02.
 
Java Core. Lecture# 3. Part# 1. Abstract classes.
Java Core. Lecture# 3. Part# 1. Abstract classes.Java Core. Lecture# 3. Part# 1. Abstract classes.
Java Core. Lecture# 3. Part# 1. Abstract classes.
 
Java. Сборщик мусора. Работа с памятью.
Java.  Сборщик мусора. Работа с памятью. Java.  Сборщик мусора. Работа с памятью.
Java. Сборщик мусора. Работа с памятью.
 
Системы контроля версий
Системы контроля версийСистемы контроля версий
Системы контроля версий
 
Bytecode
BytecodeBytecode
Bytecode
 
Java осень 2014 занятие 8
Java осень 2014 занятие 8Java осень 2014 занятие 8
Java осень 2014 занятие 8
 
C++ Базовый. Занятие 15.
C++ Базовый. Занятие 15.C++ Базовый. Занятие 15.
C++ Базовый. Занятие 15.
 

En vedette

Vijay Bhosekar_ PP_Rodale Institute_Feb 9
Vijay Bhosekar_ PP_Rodale Institute_Feb 9Vijay Bhosekar_ PP_Rodale Institute_Feb 9
Vijay Bhosekar_ PP_Rodale Institute_Feb 9
vijay bhosekar
 
C# Web. Занятие 03.
C# Web. Занятие 03.C# Web. Занятие 03.
C# Web. Занятие 03.
Igor Shkulipa
 
Mid map gaya belajar
Mid map gaya belajarMid map gaya belajar
Mid map gaya belajar
santy1301
 
Vijay Bhosekar_ PP_Rodale Institute_Feb 9
Vijay Bhosekar_ PP_Rodale Institute_Feb 9Vijay Bhosekar_ PP_Rodale Institute_Feb 9
Vijay Bhosekar_ PP_Rodale Institute_Feb 9
vijay bhosekar
 
Vijay Bhosekar_ Research Article_ Frontiers in Plant Science
Vijay Bhosekar_ Research Article_ Frontiers in Plant ScienceVijay Bhosekar_ Research Article_ Frontiers in Plant Science
Vijay Bhosekar_ Research Article_ Frontiers in Plant Science
vijay bhosekar
 
Effortless Energy Outreach Plan
Effortless Energy Outreach PlanEffortless Energy Outreach Plan
Effortless Energy Outreach Plan
Bohua Li
 

En vedette (20)

Vijay Bhosekar_ PP_Rodale Institute_Feb 9
Vijay Bhosekar_ PP_Rodale Institute_Feb 9Vijay Bhosekar_ PP_Rodale Institute_Feb 9
Vijay Bhosekar_ PP_Rodale Institute_Feb 9
 
PPC Masters February 2015
PPC Masters February 2015PPC Masters February 2015
PPC Masters February 2015
 
C# Web. Занятие 03.
C# Web. Занятие 03.C# Web. Занятие 03.
C# Web. Занятие 03.
 
Mid map gaya belajar
Mid map gaya belajarMid map gaya belajar
Mid map gaya belajar
 
Production diary 20
Production diary 20Production diary 20
Production diary 20
 
Emergency Assistance
Emergency AssistanceEmergency Assistance
Emergency Assistance
 
C# Web. Занятие 12.
C# Web. Занятие 12.C# Web. Занятие 12.
C# Web. Занятие 12.
 
Vijay Bhosekar_ PP_Rodale Institute_Feb 9
Vijay Bhosekar_ PP_Rodale Institute_Feb 9Vijay Bhosekar_ PP_Rodale Institute_Feb 9
Vijay Bhosekar_ PP_Rodale Institute_Feb 9
 
Vijay bhosekar published article organic agriculture
Vijay bhosekar  published article  organic agricultureVijay bhosekar  published article  organic agriculture
Vijay bhosekar published article organic agriculture
 
Laura mulvey’s male gaze theory
Laura mulvey’s male gaze theoryLaura mulvey’s male gaze theory
Laura mulvey’s male gaze theory
 
Advanced LinkedIn Techniques
Advanced LinkedIn TechniquesAdvanced LinkedIn Techniques
Advanced LinkedIn Techniques
 
Vijay Bhosekar_ Research Article_ Frontiers in Plant Science
Vijay Bhosekar_ Research Article_ Frontiers in Plant ScienceVijay Bhosekar_ Research Article_ Frontiers in Plant Science
Vijay Bhosekar_ Research Article_ Frontiers in Plant Science
 
Fotos de la tesis
Fotos de la tesisFotos de la tesis
Fotos de la tesis
 
psychiatry
psychiatrypsychiatry
psychiatry
 
Updated Colorado Resume
Updated Colorado Resume Updated Colorado Resume
Updated Colorado Resume
 
Production diary 15
Production diary 15Production diary 15
Production diary 15
 
Apokries2015
Apokries2015Apokries2015
Apokries2015
 
C# Web. Занятие 10.
C# Web. Занятие 10.C# Web. Занятие 10.
C# Web. Занятие 10.
 
What is Lean UX?
What is Lean UX?What is Lean UX?
What is Lean UX?
 
Effortless Energy Outreach Plan
Effortless Energy Outreach PlanEffortless Energy Outreach Plan
Effortless Energy Outreach Plan
 

Similaire à C++ STL & Qt. Занятие 08.

8. java lecture threads
8. java lecture threads8. java lecture threads
8. java lecture threads
MERA_school
 
объектно ориентированная платформа для построения
объектно ориентированная платформа для построенияобъектно ориентированная платформа для построения
объектно ориентированная платформа для построения
Gennady Zavyalov
 
Usage concurrence in java
Usage concurrence in javaUsage concurrence in java
Usage concurrence in java
Asya Dudnik
 
C++ осень 2013 лекция 4
C++ осень 2013 лекция 4C++ осень 2013 лекция 4
C++ осень 2013 лекция 4
Technopark
 
Java весна 2014 лекция 5
Java весна 2014 лекция 5Java весна 2014 лекция 5
Java весна 2014 лекция 5
Technopark
 
Android осень 2013 лекция 6
Android осень 2013 лекция 6Android осень 2013 лекция 6
Android осень 2013 лекция 6
Technopark
 
Классы и объекты в Java
Классы и объекты в JavaКлассы и объекты в Java
Классы и объекты в Java
metaform
 
Mikhail Valkov_Antipatterns
Mikhail Valkov_AntipatternsMikhail Valkov_Antipatterns
Mikhail Valkov_Antipatterns
Ciklum
 
Глава 2: Среда разработки NetBeans
Глава 2: Среда разработки NetBeansГлава 2: Среда разработки NetBeans
Глава 2: Среда разработки NetBeans
metaform
 

Similaire à C++ STL & Qt. Занятие 08. (20)

C# Desktop. Занятие 15.
C# Desktop. Занятие 15.C# Desktop. Занятие 15.
C# Desktop. Занятие 15.
 
8. java lecture threads
8. java lecture threads8. java lecture threads
8. java lecture threads
 
объектно ориентированная платформа для построения
объектно ориентированная платформа для построенияобъектно ориентированная платформа для построения
объектно ориентированная платформа для построения
 
Как пройти собеседование и получить первую работу на Swift
Как пройти собеседование и получить первую работу на SwiftКак пройти собеседование и получить первую работу на Swift
Как пройти собеседование и получить первую работу на Swift
 
Usage concurrence in java
Usage concurrence in javaUsage concurrence in java
Usage concurrence in java
 
C++ осень 2013 лекция 4
C++ осень 2013 лекция 4C++ осень 2013 лекция 4
C++ осень 2013 лекция 4
 
Java весна 2014 лекция 5
Java весна 2014 лекция 5Java весна 2014 лекция 5
Java весна 2014 лекция 5
 
C++ Базовый. Занятие 17.
C++ Базовый. Занятие 17.C++ Базовый. Занятие 17.
C++ Базовый. Занятие 17.
 
Архитектура. Доступноять программных систем.
Архитектура. Доступноять программных систем.Архитектура. Доступноять программных систем.
Архитектура. Доступноять программных систем.
 
JavaScript Базовый. Занятие 07.
JavaScript Базовый. Занятие 07.JavaScript Базовый. Занятие 07.
JavaScript Базовый. Занятие 07.
 
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
 
Android осень 2013 лекция 6
Android осень 2013 лекция 6Android осень 2013 лекция 6
Android осень 2013 лекция 6
 
Классы и объекты в Java
Классы и объекты в JavaКлассы и объекты в Java
Классы и объекты в Java
 
Working with .NET Threads
Working with .NET ThreadsWorking with .NET Threads
Working with .NET Threads
 
C# Desktop. Занятие 06.
C# Desktop. Занятие 06.C# Desktop. Занятие 06.
C# Desktop. Занятие 06.
 
Programming Java - Lection 06 - Multithreading - Lavrentyev Fedor
Programming Java - Lection 06 - Multithreading - Lavrentyev FedorProgramming Java - Lection 06 - Multithreading - Lavrentyev Fedor
Programming Java - Lection 06 - Multithreading - Lavrentyev Fedor
 
Mikhail Valkov_Antipatterns
Mikhail Valkov_AntipatternsMikhail Valkov_Antipatterns
Mikhail Valkov_Antipatterns
 
Java 9: what is there beyond modularization
Java 9: what is there beyond modularizationJava 9: what is there beyond modularization
Java 9: what is there beyond modularization
 
Асинхронность и сопрограммы
Асинхронность и сопрограммыАсинхронность и сопрограммы
Асинхронность и сопрограммы
 
Глава 2: Среда разработки NetBeans
Глава 2: Среда разработки NetBeansГлава 2: Среда разработки NetBeans
Глава 2: Среда разработки NetBeans
 

Plus de Igor Shkulipa

Общие темы. Тема 03.
Общие темы. Тема 03. Общие темы. Тема 03.
Общие темы. Тема 03.
Igor Shkulipa
 

Plus de Igor Shkulipa (20)

Общие темы. Тема 03.
Общие темы. Тема 03. Общие темы. Тема 03.
Общие темы. Тема 03.
 
Общие темы. Тема 02.
Общие темы. Тема 02.Общие темы. Тема 02.
Общие темы. Тема 02.
 
Общие темы. Тема 01.
Общие темы. Тема 01.Общие темы. Тема 01.
Общие темы. Тема 01.
 
JavaScript Базовый. Занятие 06.
JavaScript Базовый. Занятие 06.JavaScript Базовый. Занятие 06.
JavaScript Базовый. Занятие 06.
 
JavaScript Базовый. Занятие 11.
JavaScript Базовый. Занятие 11.JavaScript Базовый. Занятие 11.
JavaScript Базовый. Занятие 11.
 
JavaScript Базовый. Занятие 09.
JavaScript Базовый. Занятие 09.JavaScript Базовый. Занятие 09.
JavaScript Базовый. Занятие 09.
 
JavaScript Базовый. Занятие 10.
JavaScript Базовый. Занятие 10.JavaScript Базовый. Занятие 10.
JavaScript Базовый. Занятие 10.
 
JavaScript Базовый. Занятие 05.
JavaScript Базовый. Занятие 05.JavaScript Базовый. Занятие 05.
JavaScript Базовый. Занятие 05.
 
JavaScript Базовый. Занятие 08.
JavaScript Базовый. Занятие 08.JavaScript Базовый. Занятие 08.
JavaScript Базовый. Занятие 08.
 
JavaScript Базовый. Занятие 01.
JavaScript Базовый. Занятие 01.JavaScript Базовый. Занятие 01.
JavaScript Базовый. Занятие 01.
 
JavaScript Базовый. Занятие 04.
JavaScript Базовый. Занятие 04.JavaScript Базовый. Занятие 04.
JavaScript Базовый. Занятие 04.
 
JavaScript Базовый. Занятие 03.
JavaScript Базовый. Занятие 03.JavaScript Базовый. Занятие 03.
JavaScript Базовый. Занятие 03.
 
JavaScript Базовый. Занятие 02.
JavaScript Базовый. Занятие 02.JavaScript Базовый. Занятие 02.
JavaScript Базовый. Занятие 02.
 
C# Web. Занятие 09.
C# Web. Занятие 09.C# Web. Занятие 09.
C# Web. Занятие 09.
 
C# Web. Занятие 08.
C# Web. Занятие 08.C# Web. Занятие 08.
C# Web. Занятие 08.
 
C# Web. Занятие 07.
C# Web. Занятие 07.C# Web. Занятие 07.
C# Web. Занятие 07.
 
C# Web. Занятие 04.
C# Web. Занятие 04.C# Web. Занятие 04.
C# Web. Занятие 04.
 
C# Web. Занятие 16.
C# Web. Занятие 16.C# Web. Занятие 16.
C# Web. Занятие 16.
 
C# Web. Занятие 14.
C# Web. Занятие 14.C# Web. Занятие 14.
C# Web. Занятие 14.
 
C# Web. Занятие 15.
C# Web. Занятие 15.C# Web. Занятие 15.
C# Web. Занятие 15.
 

C++ STL & Qt. Занятие 08.

  • 1. Темы лекции: Многопоточность в Qt. Практическое задание: Многопоточность в Qt. Тренер: Игорь Шкулипа, к.т.н. С++ Библиотеки STL и Qt. Занятие 8
  • 2. http://www.slideshare.net/IgorShkulipa 2 Object Pool Применение паттерна Object Pool может значительно повысить производительность системы; его использование наиболее эффективно в ситуациях, когда создание экземпляров некоторого класса требует больших затрат, объекты в системе создаются часто, но число создаваемых объектов в единицу времени ограничено. Пулы объектов (известны также как пулы ресурсов) используются для управления кэшированием объектов. Клиент, имеющий доступ к пулу объектов может избежать создания новых объектов, просто запрашивая в пуле уже созданный экземпляр. Пул объектов может быть растущим, когда при отсутствии свободных создаются новые объекты или c ограничением количества создаваемых объектов.
  • 3. http://www.slideshare.net/IgorShkulipa 3 Реализация Object Pool на основе Singleton. Классы объектов class IObject { protected: string _strText; public: virtual void Print() { cout<<"The Object is: "<<_strText.c_str()<<"n"; } }; class Object1: public IObject { public: Object1(){ _strText="Object 1"; } }; class Object2: public IObject { public: Object2(){ _strText="Object 2"; } }; class Object3: public IObject { public: Object3(){ _strText="Object 3"; } }; class Object4: public IObject { public: Object4(){ _strText="Object 4"; } };
  • 4. http://www.slideshare.net/IgorShkulipa 4 Object Pool template<unsigned poolSize> class ObjectPool{ public: static ObjectPool* GetInstance() { if (!_instance) _instance=new ObjectPool(); return _instance; } IObject* GetObject() { for (unsigned i=0;i<poolSize;i++) { if (!_busyObjects[i]){ _busyObjects[i]=true; return _objectPool[i]; } } return NULL; } void ReleaseObject(IObject* object){ for (unsigned i=0;i<poolSize;i++) { if (_objectPool[i]==object){ _busyObjects[i]=false; } } } ...
  • 5. http://www.slideshare.net/IgorShkulipa 5 Object Pool ... private: ObjectPool(){ for (unsigned i=0;i<poolSize;i++) { unsigned iObjNumber=rand()%4; switch (iObjNumber) { case 0: _objectPool[i]=new Object1(); break; case 1: _objectPool[i]=new Object2(); break; case 2: _objectPool[i]=new Object3(); break; case 3: _objectPool[i]=new Object4(); break; } _busyObjects[i]=false; } } private: IObject* _objectPool[poolSize]; bool _busyObjects[poolSize]; static ObjectPool* _instance; };
  • 6. http://www.slideshare.net/IgorShkulipa 6 Использование Object Pool template<unsigned poolSize> ObjectPool<poolSize>* ObjectPool<poolSize>::_instance=NULL; int main() { ObjectPool<5>* op=ObjectPool<5>::GetInstance(); IObject* object1=op->GetObject(); if (object1) object1->Print(); else cout<<"The Object is: NULLn"; IObject* object2=op->GetObject(); if (object2) object2->Print(); else cout<<"The Object is: NULLn"; IObject* object3=op->GetObject(); if (object3) object3->Print(); else cout<<"The Object is: NULLn"; IObject* object4=op->GetObject(); if (object4) object4->Print(); else cout<<"The Object is: NULLn"; IObject* object5=op->GetObject(); if (object5) object5->Print(); else cout<<"The Object is: NULLn"; IObject* object6=op->GetObject(); if (object6) object6->Print(); else cout<<"The Object is: NULLn"; IObject* object7=op->GetObject(); if (object7) object7->Print(); else cout<<"The Object is: NULLn"; op->ReleaseObject(object2); IObject* object8=op->GetObject(); if (object8) object8->Print(); else cout<<"The Object is: NULLn"; }
  • 7. http://www.slideshare.net/IgorShkulipa 7 Результат The Object is: Object 2 The Object is: Object 4 The Object is: Object 3 The Object is: Object 1 The Object is: Object 2 The Object is: NULL The Object is: NULL The Object is: Object 4
  • 8. http://www.slideshare.net/IgorShkulipa 8 Преимущества и недостатки ◦ Пул объектов отслеживает объекты, которые он создает. ◦ Паттерн Object Pool может использоваться для инкапсуляции логики создания объектов. Однако он не управляет ими после их создания. ◦ Достоинством этого паттерна является быстрое создание объектов, однако это реализовано за счет использования больших ресурсов памяти.
  • 9. http://www.slideshare.net/IgorShkulipa 9 Процессы и потоки Процессы представляют собой программы, независимые друг от друга и загруженные для исполнения. Каждый процесс должен создавать хотя бы один поток, называемый основным. Основной поток процесса создается в момент запуска программы. Однако сам процесс может создавать несколько потоков одновременно. Многопоточность позволяет разделять задачи и независимо работать над каждой из них для того, чтобы максимально эффективно задействовать процессор. Написание многопоточных приложений требует больше времени и усложняет процесс отладки, поэтому многопоточность нужно применять тогда, когда это действительно необходимо. Многопоточность удобно использовать для того, чтобы блокировка или зависание одного из методов не стали причиной нарушения функционирования основной программы.
  • 10. http://www.slideshare.net/IgorShkulipa 10 QProcess Процесс — это экземпляр программы, загруженной в память компьютера для выполнения. Создание процесса может оказаться полезным для использования функциональных возможностей программ, не имеющих графического интерфейса и работающих с командной строкой. Другое полезное свойство — довольно простой запуск других программ из текущей программы. Процессы можно создавать с помощью класса QProcess, который определен в заголовочном файле QProcess. Благодаря тому, что этот класс унаследован от класса QIODevice, объекты этого класса в состоянии считывать информацию, выводимую запущенными процессами, и даже подтверждать их запросы на ввод информации. Этот класс содержит методы для манипулирования системными переменными процесса. Работа с объектами класса QProcess производится в асинхронном режиме, что позволяет сохранять работоспособность графического интерфейса программы в моменты, когда запущенные процессы находятся в работе.
  • 11. http://www.slideshare.net/IgorShkulipa 11 QThread Для использования многопоточности можно унаследовать класс от QThread и перезаписать метод run(), в который должен быть помещен код для исполнения в потоке. Чтобы запустить поток, нужно вызвать метод start(). class CustomThread : public QThread { public: CustomThread(); void setMessage(const QString &message); void run() {/*Действия потока*/}; void stop(); private: QString messageStr; volatile bool stopped; }; //... int main(int argc, char** argv) { CustomThread thread; thread.start(); }
  • 12. http://www.slideshare.net/IgorShkulipa 12 Приоритет потоков У каждого потока есть приоритет, указывающий процессору, как должно протекать выполнение потока по отношению к другим потокам. Приоритеты разделяются по группам: • в первую входят четыре наиболее часто применяемых приоритета. Их значимость распределяется по возрастанию — IdlePriority, LowestPriority, LowPriority, NormaiPriority. Они подходят для решения задач, которым процессор требуется только время от времени, например, для фоновой печати или для каких-нибудь несрочных действий; • во вторую группу входят два приоритета — HighPriority, HighestPriority. Пользуйтесь такими приоритетами с большой осторожностью. Обычно эти потоки большую часть времени ожидают какие-либо события; • в третью входят два приоритета — TimeCriticalPriority, InheritPriority. Потоки с этими приоритетами нужно создавать в случаях крайней необходимости. Эти приоритеты нужны для программ, напрямую общающихся с аппаратурой или выполняющих операции, которые ни в коем случае не должны прерваться. Для того чтобы запустить поток с нужным приоритетом, необходимо передать одно из приведенных выше значений в метод start(). Например: CustomThread thread; thread.start(QThread::IdlePriority);
  • 13. http://www.slideshare.net/IgorShkulipa 13 Синхронизация Основные сложности возникают тогда, когда потокам нужно совместно использовать одни и те же данные. Так как несколько потоков могут одновременно обращаться и записывать данные в одну область, то это может привести к нежелательным последствиям. Синхронизация позволяет задавать критические секции (critical sections), к которым в определенный момент имеет доступ только один из потоков. Это гарантирует то, что данные ресурса, контролируемые критической секцией, будут невидимы другими потоками и они не изменят их. И только после того, как поток выполнит всю необходимую работу, он освобождает ресурс, и, затем, доступ к этому ресурсу может получить любой другой поток. Например, если один поток записывает информацию в файл, то все другие не смогут использовать этот файл до тех пор, пока поток не освободит его.
  • 14. http://www.slideshare.net/IgorShkulipa 14 Объекты синхронизации Mutex Мьютексы (mutex) обеспечивают взаимоисключающий доступ к ресурсам, гарантирующий то, что критическая секция будет обрабатываться только одним потоком. Поток, владеющий мьютексом, обладает эксклюзивным правом на использование ресурса, защищенного мьютексом, и другой поток не может завладеть уже занятым мьютексом. Механизм мьютексов реализован классом QMutex. Метод lock() класса QMutex производит блокировку ресурса. Для обратной операции существует метод unlock(), который открывает закрытый ресурс для других потоков. Класс QMutex также содержит метод tryLock(). Этот метод можно использовать для того, чтобы проверить, заблокирован ресурс или нет. Этот метод не приостанавливает исполнение потока и возвращается немедленно, со значением false, если ресурс уже захвачен другим потоком, и не ожидает его освобождения. В случае успешного захвата ресурса этот метод вернет true. В сложных функциях, особенно при использовании исключений C++, легко можно ошибиться при выполнении последовательностей операций по запиранию/отпиранию мьютексов. Поэтому, в состав Qt включен класс QMutexLocker, который значительно упрощает работу с мьютексами. Конструктор класса QMutexLocker принимает объект QMutex в виде аргумента и запирает его. Деструктор класса QMutexLocker - отпирает мьютекс.
  • 15. http://www.slideshare.net/IgorShkulipa 15 Пример «Потокобезопасный стек» template <class Type> class ThreadSafeStack { public: void push(const Type& val) { mutex.lock(); stack.push(val); mutex.unlock(); } Type pop() { QMutexLocker locker (&mutex); return stack.empty() ? Type() : stack.pop(); } private: QMutex mutex; QStack<Type> stack; };
  • 16. http://www.slideshare.net/IgorShkulipa 16 QWaitCondition Библиотека Qt предоставляет класс QWaitCondition, обеспечивающий возможность координации потоков. Если поток намеревается дождаться разблокировки ресурса, то он вызывает метод QWaitCondition::wait() и, тем самым, входит в режим ожидания. Выводится он из этого режима в том случае, если поток, который заблокировал ресурс, вызовет метод QWaitCondition::wakeOne() или QWaitCondition::wakeAll(). Разница этих двух методов в том, что первый выводит из состояния ожидания только один поток, а второй — все сразу. Также для потока можно установить время, в течение которого он может ожидать разблокировки данных. Для этого нужно передать в метод wait() целочисленное значение, обозначающее временной интервал в миллисекундах.
  • 17. http://www.slideshare.net/IgorShkulipa 17 Семафоры Семафоры являются обобщением мьютексов. Как и мьютексы, они служат для защиты критических секций, чтобы доступ к ним одновременно могло иметь определенное число потоков. Все другие потоки обязаны ждать. Предположим, что программа поддерживает пять ресурсов одного и того же типа, одновременный доступ к которым может быть предоставлен только пяти потокам. Как только все пять ресурсов будут заблокированы, следующий поток, запрашивающий ресурс данного типа, будет приостановлен до освобождения одного из них. Принцип действия семафоров очень прост. Они начинают действовать с установленного значения счетчика. Каждый раз, когда поток получает право на владение ресурсом, значение этого счетчика уменьшается на единицу. И наоборот, когда поток уступает право владения этим ресурсом, счетчик увеличивается на единицу. При значении счетчика равном нулю семафор становится недоступным. Механизм семафоров реализует класс QSemaphore. Счетчик устанавливается в конструкторе при создании объекта этого класса.
  • 18. http://www.slideshare.net/IgorShkulipa 18 Взаимная блокировка При работе с многопоточностью, возможна такая ситуация, когда поток заблокировал ресурс А, а после работы над ним собирается работать с ресурсом В. Другой же поток заблокировал ресурс В и по окончании намеревается работать с ресурсом А. И вот один из потоков, закончив работу, обнаружил, что нужный ему ресурс заблокирован другим потоком. Он переходит в режим ожидания, надеясь дождаться разблокировки ресурса, но то же самое делает и другой поток. В итоге — оба ждут друг друга. Если ни один из этих потоков не освободит занятый им ресурс, то оба "зависнут" и не смогут продолжать свою работу дальше. Это явление получило название взаимной блокировки (deadlock). Существует множество решений такой проблемы. Например, можно так организовать работу потока, чтобы, в том случае, если поток не сможет получить доступ к необходимому ресурсу, он просто произвел бы освобождение занятых им ресурсов, а позже повторил попытку захвата необходимых ресурсов.
  • 19. http://www.slideshare.net/IgorShkulipa 19 Обмен сообщениями между потоками Один из важнейших вопросов при многопоточном программировании — это обмен сообщениями. Каждый поток может иметь свой собственный цикл событий. Благодаря этому можно осуществлять связь между объектами. Такая связь может производиться двумя способами: при помощи соединения сигналов и слотов или обмена событиями. Класс QObject реализован так, что обладает близостью к потокам. Каждый объект, произведенный от унаследованного от QObject класса, располагает ссылкой на поток, в котором он был создан. Эту ссылку можно получить вызовом метода QObject::thread(). Потоки осведомляют свои объекты. Благодаря этому каждый объект знает, к какому потоку он принадлежит. Обработка событий производится из контекста принадлежности объекта к потоку, то есть обработка его событий будет производиться в том потоке, которому объект принадлежит. Объекты можно перемещать из одного потока в другой с помощью метода QObject::moveToThread().
  • 20. http://www.slideshare.net/IgorShkulipa 20 Отправка событий Отправка событий — это еще одна из возможностей для осуществления связи между объектами. Есть два метода для высылки событий - QCoreApplication::postEvent() и QCoreApplication::sendEvent(). Для того чтобы объект потока был в состоянии обрабатывать получаемые события, в классе потока нужно реализовать метод QObject::event(). Если поток предназначен исключительно для отправки событий, а не для их получения, то реализацию методов обработки событий и запуск цикла обработки событий можно опустить.
  • 21. http://www.slideshare.net/IgorShkulipa 21 Сигналы и слоты Можно взять сигнал объекта одного потока и соединить его со слотом объекта другого потока. Как мы уже знаем, соединение с помощью метода connect() предоставляет дополнительный параметр, обозначающий режим обработки и равный, по умолчанию, значению Qt::AutoConnection, которое соответствует автоматическому режиму. Как только происходит высылка сигнала, Qt проверяет — происходит связь в одном и том же или разных потоках. Если это один и тот же поток, то высылка сигнала приведет к прямому вызову метода. В том случае, если это разные потоки, сигнал будет преобразован в событие и доставлен нужному объекту. Сигналы и слоты в Qt реализованы с механизмом надежности работы в потоках, а это означает, что вы можете высылать сигналы и получать, не заботясь о блокировке ресурсов.
  • 22. http://www.slideshare.net/IgorShkulipa 22 Пример «Спам-бот». См. Занятие №8. #ifndef SPAMBOT_H #define SPAMBOT_H #include <QObject> #include <QString> #include <QTime> #include "chatmessage.h" class SpamBot: public QObject { Q_OBJECT public: SpamBot(); void stop(); void run(); public slots: void handleRun(); signals: void sendSpam(); private: volatile bool stopped; }; #endif // SPAMBOT_H
  • 23. http://www.slideshare.net/IgorShkulipa 23 Реализация класса #include "spambot.h" SpamBot::SpamBot() { stopped=false; } void SpamBot::stop() { stopped=true; } void SpamBot::run() { while(!stopped) { QTime endTime= QTime::currentTime().addSecs(3); while( QTime::currentTime() < endTime ) { //Waiting... } emit sendSpam(); } } void SpamBot::handleRun() { this->run(); }
  • 24. http://www.slideshare.net/IgorShkulipa 24 Дополненный презентер class ChatClientPresenter: public QObject { Q_OBJECT public: ChatClientPresenter(ChatClient* cl, IView* v); ChatClientPresenter(IView* v); void emitRunBot() { emit runBot(); } signals: void runBot(); private slots: void DisplayMessage(); void SendMessage(); void SendMessageSpam(); private: ChatClient* client; IView* view; }; void ChatClientPresenter::SendMessageSpam() { ChatMessage message("SpamBot","Spam"); client->sendToServer(message); }
  • 25. http://www.slideshare.net/IgorShkulipa 25 Функция main #include <QtGui/QApplication> #include "mainwindow.h" #include "chatclientpresenter.h" #include "spambot.h" #include <QThread> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow* view=new MainWindow(); ChatClientPresenter* present=new ChatClientPresenter(view); view->show(); QThread *thread=new QThread(); SpamBot *spamBot=new SpamBot(); QObject::connect(spamBot, SIGNAL(sendSpam()), present,SLOT(SendMessageSpam()),Qt::QueuedConnection); QObject::connect(present, SIGNAL(runBot()), spamBot, SLOT(handleRun()), Qt::QueuedConnection); spamBot->moveToThread(thread); thread->start(); present->emitRunBot(); return a.exec(); }
  • 27. http://www.slideshare.net/IgorShkulipa 27 Лабораторная работа №8. Многопоточность Создать в тетрисе дополнительный поток, который с определенной периодичностью будет обновлять рейтинг пользователей на форме (см. Лабораторную работу №5).