Простой пример потоковой обработки в С++
Может кто-нибудь опубликовать простой пример запуска двух (объектно-ориентированных) потоков в C++.
Я ищу фактические объекты потоков C++, на которые я могу расширить методы выполнения (или что-то подобное), в отличие от вызова библиотеки потоков в стиле C.
Я пропустил любые специфичные для ОС запросы в надежде, что тот, кто ответит, ответит с использованием кроссплатформенных библиотек. Я просто делаю это прямо сейчас.
Ответы
Ответ 1
Создайте функцию, которую вы хотите выполнить, например:
void task1(std::string msg)
{
std::cout << "task1 says: " << msg;
}
Теперь создайте объект thread
, который в конечном итоге вызовет функцию выше, например:
std::thread t1(task1, "Hello");
(Для доступа к классу std::thread
необходимо #include <thread>
)
Аргументы конструктора - это функция, которую будет выполнять поток, а затем параметры функции. Нить автоматически запускается при строительстве.
Если позже вы хотите дождаться выполнения потока, выполняющего эту функцию, вызовите:
t1.join();
(Соединение означает, что поток, который вызвал новый поток, будет ждать завершения нового потока, прежде чем он продолжит свое собственное исполнение).
Код
#include <string>
#include <iostream>
#include <thread>
using namespace std;
// The function we want to execute on the new thread.
void task1(string msg)
{
cout << "task1 says: " << msg;
}
int main()
{
// Constructs the new thread and runs it. Does not block execution.
thread t1(task1, "Hello");
// Do other things...
// Makes the main thread wait for the new thread to finish execution, therefore blocks its own execution.
t1.join();
}
Дополнительная информация о std :: thread here
- В GCC скомпилируйте с
-std=c++0x -pthread
. - Это должно работать для любой операционной системы, если ваш компилятор поддерживает эту функцию (С++ 11).
Ответ 2
Ну, технически любой такой объект будет построен поверх библиотеки потоков C-стиля, потому что С++ только что указала запас std::thread
модель в С++ 0x, которая была просто прибита и еще не реализована. Проблема несколько системная, технически существующая модель памяти С++ не является достаточно строгой, чтобы допускать четко определенную семантику для всех случаев "случится раньше". Ханс Бем написал статью по теме некоторое время назад и сыграл важную роль в том, чтобы выбить стандарт С++ 0x по теме.
http://www.hpl.hp.com/techreports/2004/HPL-2004-209.html
Тем не менее, существует несколько кросс-платформенных библиотек С++, которые отлично работают на практике. Блоки построения потоков Intel содержат объект tbb:: thread, который близко аппроксимирует стандарт С++ 0x, а Boost имеет библиотеку boost:: thread, которая делает то же самое.
http://www.threadingbuildingblocks.org/
http://www.boost.org/doc/libs/1_37_0/doc/html/thread.html
Используя boost:: thread, вы получите что-то вроде:
#include <boost/thread.hpp>
void task1() {
// do stuff
}
void task2() {
// do stuff
}
int main (int argc, char ** argv) {
using namespace boost;
thread thread_1 = thread(task1);
thread thread_2 = thread(task2);
// do other stuff
thread_2.join();
thread_1.join();
return 0;
}
Ответ 3
Существует также библиотека POSIX для операционных систем POSIX. Проверьте совместимость
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <iostream>
void *task(void *argument){
char* msg;
msg = (char*)argument;
std::cout<<msg<<std::endl;
}
int main(){
pthread_t thread1, thread2;
int i1,i2;
i1 = pthread_create( &thread1, NULL, task, (void*) "thread 1");
i2 = pthread_create( &thread2, NULL, task, (void*) "thread 2");
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
return 0;
}
скомпилировать с -lpthread
http://en.wikipedia.org/wiki/POSIX_Threads
Ответ 4
#include <thread>
#include <iostream>
#include <vector>
using namespace std;
void doSomething(int id) {
cout << id << "\n";
}
/**
* Spawns n threads
*/
void spawnThreads(int n)
{
std::vector<thread> threads(n);
// spawn n threads:
for (int i = 0; i < n; i++) {
threads[i] = thread(doSomething, i + 1);
}
for (auto& th : threads) {
th.join();
}
}
int main()
{
spawnThreads(10);
}
Ответ 5
При поиске примера класса С++, который вызывает один из своих методов экземпляра в новом потоке, этот вопрос возникает, но мы не смогли использовать какой-либо из этих ответов таким образом. Вот пример, который делает это:
Class.h
class DataManager
{
public:
bool hasData;
void getData();
bool dataAvailable();
};
Class.cpp
#include "DataManager.h"
void DataManager::getData()
{
// perform background data munging
hasData = true;
// be sure to notify on the main thread
}
bool DataManager::dataAvailable()
{
if (hasData)
{
return true;
}
else
{
std::thread t(&DataManager::getData, this);
t.detach(); // as opposed to .join, which runs on the current thread
}
}
Обратите внимание, что этот пример не попадает в мьютекс или блокировку.
Ответ 6
Если в глобальных именах не требуется отдельная функция, мы можем использовать лямбда-функции для создания потоков.
Одним из основных преимуществ создания потока с использованием лямбда является то, что нам не нужно передавать локальные параметры в виде списка аргументов. Мы можем использовать список захвата для того же самого, и свойство закрытия lambda позаботится о жизненном цикле.
Вот пример кода
int main() {
int localVariable = 100;
thread th { [=](){
cout<<"The Value of local variable => "<<localVariable<<endl;
}}
th.join();
return 0;
}
На сегодняшний день я нашел С++ lambdas лучшим способом создания потоков, особенно для более простых функций потока.
Ответ 7
В значительной степени это зависит от библиотеки, которую вы решили использовать. Например, если вы используете библиотеку wxWidgets, создание потока будет выглядеть так:
class RThread : public wxThread {
public:
RThread()
: wxThread(wxTHREAD_JOINABLE){
}
private:
RThread(const RThread ©);
public:
void *Entry(void){
//Do...
return 0;
}
};
wxThread *CreateThread() {
//Create thread
wxThread *_hThread = new RThread();
//Start thread
_hThread->Create();
_hThread->Run();
return _hThread;
}
Если ваш основной поток вызывает метод CreateThread, вы создадите новый поток, который начнет выполнять код в вашем методе "Enter". В большинстве случаев вам нужно будет ссылаться на поток, чтобы присоединиться или остановить его.
Подробнее здесь: документация wxThread
Ответ 8
//multithread.cpp: простой пример потоковой обработки в C++, который использует потоки и критический раздел.
#include "stdafx.h"
#include <thread>
#include <iostream>
#include<fstream>
#include <windows.h>
using namespace std;
bool flag = 1;
auto path = "D:\\temp";
void writestatus(int i, int j);
CRITICAL_SECTION cs;
void workerThread(int j)
{
int i = 1;
ofstream f2;
char buff[150] = { 0 };
while (flag)
{
sprintf_s(buff, 150, "D:\\temp\\MyTemp_%d%03d.txt", j, i++);
//str.append("%d", i++);
f2.open(buff);
f2 << buff;
f2.close();
//Sleep(10);
}
EnterCriticalSection(&cs);
writestatus(i, j);
LeaveCriticalSection(&cs);
}
void writestatus(int i, int j)
{
ofstream f1;
char buff[150] = { 0 };
f1.open("D:\\temp\\status.txt", ios_base::app);
sprintf_s(buff, 150, "%d Writes %d files \n", j, i++);
if (f1)
{
f1 << buff;
}
else
{
MessageBeep(1);
}
f1.close();
}
int main()
{
system("del d:\\temp\\*.txt");
InitializeCriticalSection(&cs);
thread t1(workerThread, 1);
thread t2(workerThread, 2);
thread t3(workerThread, 3);
thread t4(workerThread, 4);
thread t5(workerThread, 5);
Sleep(250);
flag = 0;
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
return 0;
}