From the course: Python Essential Training

Multithreading - Python Tutorial

From the course: Python Essential Training

Multithreading

- [Instructor] Processes and threads may seem like abstract concepts right now, but let's get hands-on and start spinning some up. The other programmers are going to look at your code and say, "Nice threads." The first thing we want to do is import the threading and time modules. So import threading, import time. Then we're going to create a function that calculates the square of a number but takes a really long time to do it. We can call it, appropriately, longSquare. You pass in a number time.sleep for a whole second and then return that number squared. Let's say we want to calculate the square of a few numbers. It's going to take a long time. For in and range zero through five. This is obviously a fairly contrived example, but these situations often arise in programming. For instance, waiting to fetch data back from a remote server. Your code is just sitting around doing nothing, waiting for that data to come back, and this is where threads come in handy. So you can do all that waiting in parallel rather than one at a time. To demonstrate this, we're going to make two threads. t1 is threading.thread. And then t2, threading.thread. We're going to pass in two keyword arguments. The first one is called target, and that's the name of the target function, longSquare. The second is called args. That's going to be the arguments we pass to the function. And let's copy this and put it there. Okay, now I'm putting a comma after this, just to show Python that it's a tuple and not a random variable with parentheses around it. If you only have one value in the tuple, sometimes that's necessary. Okay, now we need to start both of the threads with the start function, t1.start t2.start. And finally, we join them, t1.join t2.join. This join function checks to see if the thread has completed execution yet and pauses until execution's complete. And you can see this runs in about half the time it would take us to run these one at a time. But one little problem, where are the results of our function? You might try to get the results from the thread object by saying t1.results return value, but I promise you're not going to find it. The return value of this function is actually nowhere in these threads. There is no way to get the output of this function directly, so here's where we can take advantage of the fact that threads share memory. Let's create a results dictionary and bring this code down here and modify our function so that that results dictionary gets passed in. Then rather than returning anything, it's going to take results and then just add it to the dictionary. Okay, and pass in results, results. Just bring that down there to keep things organized. Whoops, there. Finally, print results. And there you go. Threads share memory and can modify the same object. Of course, writing out t1, t2, start, join is laborious if we want lots and lots of values or a variable number of values back. So it's a common pattern to put all these into a list, so let's do that. Let's make a list called threads, plural, and say threading.thread. Target is going to be longSquare, args. It's going to be n, results for n in range 0, 10. Okay, then we need to say t1., or sorry, t.start for t in threads. And finally, t.join for t in threads. And then we can print results. That was fast. And just for fun, let's do 100 threads. (laughs) Much faster than waiting one at a time.

Contents