天天看點

C++11多線程的建立

#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <thread>

namespace thread_create {

// 參考:https://www.codeproject.com/Articles/598695/Cplusplus-threads-locks-and-condition-variables
// http://www.cnblogs.com/haippy/p/3284540.html

static void Test1(int x, const std::string& y) {
  std::cout << x << y << std::endl;

  for (int i = 0; i < 100; ++i) {
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    std::cout << i << std::endl;
  }
}

// 1.建立線程時可以把多個參數傳進去。
static void Demo1() {
  std::thread thread(Test1, 1, "test");

  for (char i = 'a'; i < 'z'; ++i) {
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    std::cout << i << std::endl;
  }

  // 如果不掉用join或者detach,會抛出異常。
  thread.join();
  //thread1.detach();
}

//------------------------------------------------------------------

class Class01 {
public:
  Class01() {
    std::cout << "Class01 construct!" << std::endl;
  }

  Class01(const Class01& c) {
    if (this != &c) {
      std::cout << "Class01 copy construct!" << std::endl;
    }
  }
};

static void Test2(int& x) {
  x++;
}

static void Test21(const Class01& c) {
  std::cout << "Test21" << std::endl;
}

// 2.參數傳值預設的是傳值。如果是傳遞引用,需要使用std::ref,std::cref。
// 也就是說如果線程函數是非const引用,我們傳值的時候必須用std::ref,
// 否則會編譯出錯。
static void Demo2() {
  int a = 10;

  // (A)編譯出錯,因為第二個參數不是左值,是以不能直接傳給引用。
  //std::thread thread(Test2, 2);

  // (B)同樣編譯不過,函數的參數是非const引用,則必須用std::ref。
  //std::thread thread(Test2, a);

  // (C)編譯通過。
  //std::thread thread(Test2, std::ref(a));
  //thread.join();
  // 輸出11,說明直接傳的引用而不是傳值。
  //std::cout << a << std::endl;

  // (D)實際上這個建立過程有兩次參數傳遞。第一次是将參數傳給std::thread
  // 的構造函數,第二次是std::thread将參數傳給線程函數。
  Class01 c;
  // 會調用一次Class01的拷貝構造函數,因為将c傳給std::thread進行了一次拷貝,
  // 而std::thread将c傳給Test21沒有進行拷貝,因為Test21的參數是const引用。
  // 如果将Test21的參數是改為傳值,則進行兩次拷貝構造。
  //std::thread thread(Test21, c);
  //thread.join();

  // 沒有調用拷貝構造。
  std::thread thread(Test21, std::ref(c));
  thread.join();
}

//------------------------------------------------------------------

// 3.std::this_thread
// get_id: returns the id of the current thread
// yield : tells the scheduler to run other threads and can be used when you are in a busy waiting state
// sleep_for : blocks the execution of the current thread for at least the specified period
// sleep_util : blocks the execution of the current thread until the specified moment of time has been reached


}  // namespace thread_create

//------------------------------------------------------------------

int main() {
  Demo1();
  Demo2();

  return 0;
}