1.不同平台线程的使用
1.1 windows平台线程示例
#include <windows.h>
#include <process.h>
#include <iostream>
// 线程函数,参数和返回值必须符合要求
DWORD WINAPI print_hello(LPVOID p)
{
std::cout << "hello\n" << std::endl;
return 0;
}
DWORD WINAPI print_world(LPVOID p)
{
std::cout << "world\n" << std::endl;
return 0;
}
int main() {
HANDLE hThread1, hThread2;
unsigned threadId1, threadId2;
hThread1 = CreateThread(nullptr, 0, print_hello, nullptr, 0, nullptr);
if (hThread1 == nullptr) {
std::cerr << "线程创建失败" << std::endl;
return 1;
}
hThread2 = CreateThread(nullptr, 0, print_world, nullptr, 0, nullptr);
if (hThread2 == nullptr) {
std::cerr << "线程创建失败" << std::endl;
return 1;
}
// 等待线程结束
WaitForSingleObject(hThread1, INFINITE);
WaitForSingleObject(hThread2, INFINITE);
// 关闭线程句柄
CloseHandle(hThread1);
CloseHandle(hThread2);
return 0;
}
1.2 linux平台线程示例
//pthread创建线程
#include <pthread.h>
#include <iostream>
using namespace std;
void* print_hello(void* arg)
{
cout << "hello" << endl;
}
void* print_world(void* arg)
{
cout << "world" << endl;
}
int main()
{
cout << "start" << endl;
pthread_t t1;
pthread_t t2;
pthread_create(&t1, NULL, print_hello, NULL);
pthread_create(&t2, NULL, print_world, NULL);
pthread_join(t1, nullptr);
//pthread_join(t2, nullptr);
pthread_detach(t2);
//cout << "end" << endl;
return 0;
}
2.C++11线程库的使用
#include <thread>
#include <iostream>
using namespace std;
void print_hello()
{
cout << "hello" << endl;
}
void print_chenglin()
{
cout << "chenglin" << endl;
}
int main()
{
cout << "test start" << endl;
cout << "main thread id:" << this_thread::get_id() << endl;
thread t1(print_hello);
cout << "hello thread id:" << t1.get_id() << endl;
t1.detach();
thread t2(print_chenglin);
cout << "chenglin thread id:" << t2.get_id() << endl;
t2.detach();
//this_thread::sleep_for(chrono::seconds(5));
if(t1.joinable())
{
cout << "t1 thread running ...." << endl;
t1.join();
}
else
{
cout << "t1 thread end" << endl;
}
if(t2.joinable())
{
cout << "t2 thread running ...." << endl;
t2.join();
}
else
{
cout << "t2 thread end" << endl;
}
cout << "test end" << endl;
return 0;
}
3.定义头文件
//thread.h
#ifndef __THREAD_H__
#define __THREAD_H__
#include <iostream>
#include <functional>
#include <memory>
// 线程函数包装器(在头文件中声明,因为模板中使用)
#ifdef _WIN32
DWORD WINAPI threadFunction(LPVOID arg);
#else
void* threadFunction(void* arg);
#endif
#endif
// 用于存储线程函数和参数的结构体(在头文件中定义,因为模板中使用)
struct ThreadData {
std::function<void()> func;
ThreadData(std::function<void()>&& f) : func(std::move(f)) {}
};
class thread {
public:
thread() noexcept;
template< class F, class... Args >
explicit thread( F&& f, Args&&... args );
~thread();
void join();
void detach();
bool joinable() const noexcept;
uint64_t get_id() const noexcept;
private:
uint64_t m_threadID;
};
template< class F, class... Args >
thread::thread( F&& f, Args&&... args ) : m_threadID(0) {
auto func = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
std::unique_ptr<struct ThreadData> data(new struct ThreadData(std::move(func)));
#ifdef _WIN32
HANDLE hThread = CreateThread(nullptr, 0, &threadFunction, data.release(), 0, nullptr);
if (hThread!= nullptr) {
m_threadID = reinterpret_cast<uint64_t>(hThread);
}
#else
pthread_t pthread;
pthread_create(&pthread, nullptr, &threadFunction, data.release());
m_threadID = reinterpret_cast<uint64_t>(pthread);
#endif
}
4.定义不同平台源文件
4.1 windows平台
//thread_win.cpp
#ifdef _WIN32
#include "thread.h"
#include <windows.h>
#include <cstdint>
// 线程函数包装器定义
DWORD WINAPI threadFunction(LPVOID arg) {
std::unique_ptr<ThreadData> data(static_cast<ThreadData*>(arg));
data->func();
return 0;
}
thread::thread() noexcept : m_threadID(0) {
}
thread::~thread() {
// 如果线程还未分离且可连接,进行清理
if (joinable()) {
HANDLE hThread = reinterpret_cast<HANDLE>(m_threadID);
CloseHandle(hThread);
}
}
void thread::join() {
if (joinable()) {
HANDLE hThread = reinterpret_cast<HANDLE>(m_threadID);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
m_threadID = 0;
}
}
void thread::detach() {
if (joinable()) {
HANDLE hThread = reinterpret_cast<HANDLE>(m_threadID);
CloseHandle(hThread);
m_threadID = 0;
}
}
bool thread::joinable() const noexcept {
return m_threadID!= 0;
}
uint64_t thread::get_id() const noexcept {
return m_threadID;
}
#endif
4.2 linux平台
//thread_posix.cpp
#ifndef _WIN32
#include "thread.h"
#include <pthread.h>
#include <cstdint>
// 线程函数包装器定义
void* threadFunction(void* arg) {
std::unique_ptr<ThreadData> data(static_cast<ThreadData*>(arg));
data->func();
return nullptr;
}
thread::thread() noexcept : m_threadID(0) {
}
thread::~thread() {
// 如果线程还未分离且可连接,进行清理
if (joinable()) {
pthread_t pthread = reinterpret_cast<pthread_t>(m_threadID);
pthread_detach(pthread);
}
}
void thread::join() {
if (joinable()) {
pthread_t pthread = reinterpret_cast<pthread_t>(m_threadID);
pthread_join(pthread, nullptr);
m_threadID = 0;
}
}
void thread::detach() {
if (joinable()) {
pthread_t pthread = reinterpret_cast<pthread_t>(m_threadID);
pthread_detach(pthread);
m_threadID = 0;
}
}
bool thread::joinable() const noexcept {
return m_threadID!= 0;
}
uint64_t thread::get_id() const noexcept {
return m_threadID;
}
#endif
5.测试程序
//main.cpp
#include "thread.h"
#include <iostream>
using namespace std;
void print_hello()
{
cout << "hello" << endl;
}
void print_world()
{
cout << "world" << endl;
}
int main()
{
cout << "start" << endl;
thread t1(print_hello);
thread t2(print_world);
//t1.join();
//t2.join();
t1.detach();
t2.detach();
cout << "end" << endl;
return 0;
}
6.编译运行
//CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
set(EXECUTABLE_NAME "thread")
project(${EXECUTABLE_NAME})
set(CMAKE_CXX_STANDARD 11)
# 根据操作系统添加源文件
if(WIN32)
add_executable(${EXECUTABLE_NAME} main.cpp thread_win.cpp)
else()
add_executable(${EXECUTABLE_NAME} main.cpp thread_posix.cpp)
endif()
# 链接库
if(WIN32)
# Windows下无需额外链接库
else()
target_link_libraries(${EXECUTABLE_NAME} pthread)
endif()
编译:
mkdir build
cd build
cmake ../
make
运行输出:
chenglin@ubuntu:~/work/Thread/Project/MyThread/build$ ./thread
start
hello
end
world