Работа с потоками boost::thread

Рубрика: C++, Дата: 2 April, 2015, Автор:

boostЗдорова ребятки, сегодня разберем такую штуку как boost::thread. Эта библиотека предназначена для создания потоков. Как подключить и настроить boost вы можите почитать по ссылке Подключени и работа boost в visual studio 2010.  Разберем несколько примеров как создаются потоки.


 

Содержание:

1. Вызов функции выполняющейся в потоке
2. Вызов функции с параметрами выполняющейся в потоке
3. Использование функтора
4. Объектный в котором передается функция в поток
5. Объектный способ, который управляет своими потоками


1. Вызов функции выполняющейся в потоке

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

#include <boost/thread/thread.hpp>
#include <iostream>
using std::cout;
using std::endl;

void f1()
{
	cout <<"Hello world, I'm a thread1!"<<endl;
}
void f2()
{
	cout <<"Hello world, I'm a thread2!"<<endl;
}

int main()
{
	boost::thread t1(&f1);//вызываем функцию f1
	boost::thread t2(&f2);//добавляем функцию f2 в поток
	t1.join();//ждем завершение потока t1
	t2.join();//ждем завершение потока t2
	//Оба потока завершены используем их результаты
	
	return 0;
}

Выводится на экран:

result output

2. Вызов функции с параметрами выполняющейся в потоке

Теперь рассмотрим пример кода в котором мы вызовем уже функцию с параметрами в потоках. Функцию можно передавать и просто по значению как в коде ниже

#include <boost/thread/thread.hpp>
#include <iostream>
using std::cout;
using std::endl;

void f1(double n,int k)
{
	cout <<"Hello world, I'm a thread n= "<<n<<" k= "<<k<<endl;
}

int main()
{
	boost::thread t1(f1,1,10);//вызываем функцию f1
	boost::thread t2(f1,2,20);//добавляем функцию f1 в поток
	boost::thread t3(&f1,3,30);//добавляем функцию f1 в поток
	boost::thread t4(&f1,4,40);//добавляем функцию f1 в поток
	t1.join();
	t2.join();
	t3.join();
	t4.join();
	//ждем пока все потоки будут завершены
	
	return 0;
}

Вывод на экран:

command output3. Использование функтора

Функтор – это класс в котором перегружен operator(), который благодаря этому может вести себя и как объект и как функция одновременно. Метод определенный при перегрузке () срабатывает при вызове объекта как функции.

Ниже пример кода с функтором который вычисляет куб в несколько потоков

#include <boost/thread/thread.hpp>
#include <iostream>
using std::cout;
using std::endl;

//создаем функтор для подсчета куба
class kyb
{
	double n;
public:
	kyb(double a):n(a){}//конструктор

	void operator()()//вычисление будет производится при вычислении
	{
		double k=n*n*n;
		cout <<"n= "<<n<<" kyb= "<<k<<endl;
	}
};

int main()
{
	//создаем объекты
	kyb k1(1);
	kyb k2(2);
	kyb k3(3);
	kyb k4(3);

	//создаем потоки
	boost::thread t1(k1);//вызываем функцию f1
	boost::thread t2(k2);//добавляем функцию f1 в поток
	boost::thread t3(k3);//добавляем функцию f1 в поток
	boost::thread t4(k4);//добавляем функцию f1 в поток
	
	t1.join();
	t2.join();
	t3.join();
	t4.join();
	//ждем пока все потоки будут завершены
	
	//вызов просто объектов как функций без потоков
	cout <<"_____________"<<endl;
	k1();
	k2();
	k3();
	k4();
	
	return 0;
}

Вывод на экран:

command1 output

Важно понимать, что конструктор boost::thread берет функтор-параметр по значению, что означает создание копии объекта.
Не стоит забывать об этом при реализации функтора, чтобы избежать возможных проблем.

4. Объектный в котором передается функция в поток

В данном способе в конструктор boost::tread необходимо передать имя функции используя имя класса, ссылку на экземпляр класса и при необходимости параметр. В примере ниже мы вычисляем куб и с помощью третьего параметра умножаем его на 2 и выводим на экран

#include <boost/thread/thread.hpp>
#include <iostream>
using std::cout;
using std::endl;

//создаем функтор для подсчета куба
class kyb
{
	double n;
public:
	kyb(double a):n(a){}//конструктор

	void raschet_cub(double a)//вычисление будет производится при вычислении
	{
		double k=n*n*n*a;
		cout <<"n= "<<n<<" a= "<<a<<" kyb= "<<k<<endl;
	}
};

int main()
{
	//создаем объекты
	kyb k1(1);
	kyb k2(2);
	kyb k3(3);
	kyb k4(3);

	//создаем потоки и вызываем функцию из объекта kyb::raschet_cub
	boost::thread t1(&kyb::raschet_cub,&k1,2);
	boost::thread t2(&kyb::raschet_cub,&k2,2);
	boost::thread t3(&kyb::raschet_cub,&k3,2);
	boost::thread t4(&kyb::raschet_cub,&k4,2);
	
	t1.join();
	t2.join();
	t3.join();
	t4.join();
	//ждем пока все потоки будут завершены
	
	return 0;
}

Вывод на экран:

command2

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

5. Объектный способ, который управляет своими потоками

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

В коде ниже поток создается внутри объекта, а сам объект предоставляет методы для управления потоком. Смотрим код.

#include <boost/thread/thread.hpp>
#include <iostream>
using std::cout;
using std::endl;

//создаем функтор для подсчета куба
class kyb
{
	boost::thread Thread;//хранит поток
public:
	kyb(){}//конструктор

	//создание потока
	void start(double n)//создаем поток
	{
		Thread=boost::thread(&kyb::raschet_cub,this,n);//создается поток
	}

	//закрытие потока
	void join()
	{
		Thread.join();
	}

	//функция рассчитывает куб числа
	void raschet_cub(double n)//вычисление будет производится при вычислении
	{
		double k=n*n*n;
		cout <<"n= "<<n<<" kyb= "<<k<<endl;
	}
};

int main()
{
	//создаем объекты
	kyb k1;
	kyb k2;
	kyb k3;
	kyb k4;

	//создаем потоки и вызываем функцию из объекта kyb::raschet_cub
	k1.start(1);
	k2.start(2);
	k3.start(3);
	k4.start(4);
	
	k1.join();
	k2.join();
	k3.join();
	k4.join();
	//ждем пока все потоки будут завершены
	
	return 0;
}

Вывод на экран:

command3

На этом пожалуй все, в принципе понятно как использовать потоки, тут ничего сложного нету 🙂

[youtube]https://www.youtube.com/watch?v=OAhHX2LheMI[/youtube]

 

 

Комментарии:


Оставить комментарий

Your email address will not be published. Required fields are marked *