We already discussed the difference between Thread and Process. Today let’s discuss more details about Thread, and run a sample code.
Example 1: Easiest Thread
After C++ we can use thread class by #include<thread>
. And this is the function we want to run in our new thread:
#include<thread>
#include <iostream>void playGame(int hour) {
for (int i=0; i< hour; i++) {
std::cout<< "played "<<i<<" hour.\n";
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
}
STEP 1
Now to create a thread object, we simply pass the function we want to execute in the new thread object.
int main() {
int hour = 0;
std::thread my_thread(playGame, hour); // STEP 1
return 0;
}
Notice:
playGame
is an callable: could be (1) function pointer, (2) function object or (3) lambda expressionhour
is a parameter to pass to the functionplayGame
, there could be more than one parameter
Once my_thread is created, the callable start running.
STEP 2
While we have the new thread mythread
, in a certain time in the future, we do want to comeback to our main thread. But we need to first wait until mythread
has done its job.
int main() {
int hour = 0;
std::thread my_thread(playGame, hour); // STEP 1
my_thread.join(); // STEP 2
printf("swap back to main");
return 0;
}
std::thread::join()
will wait until is done, then swap back to main thread.
Thats it. Final code looks like this:
#include<thread>
#include <iostream>
void playGame(int hour) {
for (int i=0; i< hour; i++) {
std::cout<< "played "<<i<<" hour.\n";
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
}
int main() {
int hour = 0;
std::thread my_thread(playGame, hour);
my_thread.join();
printf("swap back to main");
return 0;
}
Output:
played 1 hour.
played 2 hour.
swap back to main
Example 2: Why use it at all?
In one sentence: in ideal case, multithread helps your program to speed up with concurrency mechanism. The following example will show how the concurrency works:
Image you are playing game while listening to music, and your dinner is in the oven.
#include<thread>
#include <iostream>
// 1. callable = function pointer
void playGame(int hour) {
for (int i=0; i< hour; i++) {
std::cout<< "Task 1: played "<<i<<" hour.\n";
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
}// 2. callable = function object
class Dinner {
public:
void cook(std::string name, int hour) {
for (int i=0; i<hour; i++) {
std::cout<<"Task 2: dinner "<< name << " is baked for "<< i <<"hour. \n";
}
}
};
// 3. callable = lambda expression
auto music = [](int count) {
for (int i = 0; i < count; i++) {
std::cout<<"Task 3: listened to "<< i << " song. \n";
}
};
int main() {
std::thread my_thread_1(playGame, 2);
std::thread my_thread_2(&Dinner::cook, Dinner(), "lasagna", 3);
std::thread my_thread_3(music, 3);
my_thread_1.join();
my_thread_2.join();
my_thread_3.join();
printf("swap back to main");
return 0;
}
Note: the 2. callable — function object, like it’s name, it need parameter like the following:
std::thread my_thread_2(
&Dinner::cook, //class's function
Dinner(), //class object
"lasagna", 3 //parameter of the function
);
The output of the program is differ by your OS. You could get this:
Task 2: dinner lasagna is baked for 0hour.
Task 2: dinner lasagna is baked for 1hour.
Task 2: dinner lasagna is baked for 2hour.
Task 3: listened to 0 song.
Task 3: listened to 1 song.
Task 3: listened to 2 song.
Task 1: played 0 hour.
Task 1: played 1 hour.
swap back to main
or this:
Task 3: listened to 0 song.
Task 1: played Task 2: dinner lasagna is baked for 0hour.
Task 2: dinner lasagna is baked for 0Task 3: listened to 1 hour.
1 song.
Task 3: listened to 2 song.
hour.
Task 2: dinner lasagna is baked for 2hour.
Task 1: played 1 hour.
swap back to main
or any other…