Welcome! With our recent lessons, you've gained a strong foundation in creating and managing threads, as well as understanding data sharing between threads using primitive approaches. Now, it's time to put all that knowledge into practice by building a simple multithreaded application.
In this project, you will create a basic program that simulates downloading files concurrently. This will involve:
-
Creating a
Downloader
Class:- The
Downloader
class represents a task that downloads a file. - You will use threads to execute instances of this class concurrently, simulating asynchronous downloads.
- The
-
Simulating File Downloads with Delays:
- To make the downloads feel realistic, we'll introduce delays using
std::this_thread::sleep_for
. - This will also help you understand how to manage and coordinate multiple threads working over time.
- To make the downloads feel realistic, we'll introduce delays using
-
Managing Multiple Threads:
- You'll learn how to start multiple download threads and ensure they complete correctly.
- Methods such as
join()
anddetach()
will be crucial here, ensuring that the main program waits for all downloads to finish before proceeding.
Here's a preview of what you'll be working towards:
C++1#ifndef DOWNLOADER_H 2#define DOWNLOADER_H 3 4#include <iostream> 5#include <string> 6#include <thread> 7#include <chrono> 8#include <random> 9 10class Downloader { 11public: 12 Downloader(const std::string& fileName) : fileName_(fileName), rndEngine_(std::random_device{}()) {} 13 14 void operator()() { 15 try { 16 std::cout << "Downloading " << fileName_ << std::endl; 17 std::uniform_int_distribution<int> dist(100, 200); 18 std::this_thread::sleep_for(std::chrono::milliseconds(dist(rndEngine_))); 19 std::cout << "Completed " << fileName_ << std::endl; 20 } catch (...) { 21 std::cout << "Download interrupted for " << fileName_ << std::endl; 22 } 23 } 24 25private: 26 std::string fileName_; 27 std::mt19937 rndEngine_; 28}; 29 30#endif // DOWNLOADER_H 31 32int main() { 33 std::thread t1(Downloader("file1.txt")); 34 std::thread t2(Downloader("file2.txt")); 35 t1.join(); 36 t2.join(); 37 std::cout << "All downloads completed" << std::endl; 38 return 0; 39}
Let's break down the code snippet above:
- The
Downloader
class represents a task that downloads a file. It takes the file name as a parameter and simulates a download operation.- The
std::uniform_int_distribution
objectdist
generates random delays between 100 and 200 milliseconds. - The
std::this_thread::sleep_for
function pauses the thread for the specified duration.- Note, that we use
std::chrono::milliseconds
to specify the duration in milliseconds and therndEngine_
object is used to generate random numbers for the delay. We seed it withstd::random_device{}
to ensure different sequences each time.
- Note, that we use
- The
operator()
function is the entry point for the thread, where the download operation is performed.
- The
- In the
main
function:- We create two threads
t1
andt2
, each executing an instance of theDownloader
class with different file names. - We use the
join()
method to wait for both threads to complete before printing "All downloads completed".
- We create two threads
Understanding how to create and manage a multithreaded application is crucial for several reasons:
- Real-World Applications: Many real-world applications require handling multiple tasks simultaneously, such as web servers managing multiple requests or programs performing background downloads.
- Efficiency: Multithreading can significantly improve the efficiency of your programs by allowing tasks to run concurrently, making better use of system resources.
- Skill Enhancement: Mastering these concepts will enhance your programming skills and make you proficient in handling complex concurrency issues.
Ready to take your skills to the next level? Let's dive into the practice project and bring your multithreading knowledge to life.