Can you start a thread twice python?
I want to start the same timer twice so I can stop that same timer. When I try this: Show
I get EDITED I want to create a repeating timer. I need to use the same thread so I can call ExampleIt was most frequent question that can a same thread can be run twice. The answer for this is know one thread can run only once . if you try to run the same thread twice it will execute for the first time but will give error for second time and the error will be IllegalThreadStateException . example:
output: Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Threading in Python Python threading allows you to have different parts of your program run concurrently and can simplify your design. If you’ve got some experience in Python and want to speed up your program using threads, then this tutorial is for you! In this article, you’ll learn:
This article assumes you’ve got the Python basics down pat and that you’re using at least version 3.6 to run the examples. If you need a refresher, you can start with the Python Learning Paths and get up to speed. If you’re not sure if you want to use Python All of the sources used in this tutorial are available to you in the Real Python GitHub repo. What Is a Thread?A thread is a separate flow of execution. This means that your program will have two things happening at once. But for most Python 3 implementations the different threads do not actually execute at the same time: they merely appear to. It’s tempting to think of threading as having two (or more) different processors running on your program, each one doing an independent task at the same time. That’s almost right. The threads may be running on different processors, but they will only be running one at a time. Getting multiple tasks running simultaneously requires a non-standard implementation of Python, writing some of your code in a different language, or
using Because of the way CPython implementation of Python works, threading may not speed up all tasks. This is due to interactions with the GIL that essentially limit one Python thread to run at a time. Tasks that spend much of their time waiting for external events are generally good candidates for threading. Problems that require heavy CPU computation and spend little time waiting for external events might not run faster at all. This is true for code written in Python and running on the standard CPython implementation. If your threads are written in C they have the ability to release the GIL and run concurrently. If you are running on a different Python implementation, check with the documentation too see how it handles threads. If you are running a standard Python implementation, writing in only Python, and have a CPU-bound problem, you should
check out the Architecting your program to use threading can also provide gains in design clarity. Most of the examples you’ll learn about in this tutorial are not necessarily going to run faster because they use threads. Using threading in them helps to make the design cleaner and easier to reason about. So, let’s stop talking about threading and start using it! Starting a ThreadNow that you’ve got an idea of what a thread is, let’s learn how to make one. The Python standard library provides To start a separate thread, you create a
If you look around the logging statements, you can see that the
When you create a For this article, you’ll use sequential integers as names for your threads. There is
When you run this program as it is (with line twenty commented out), the output will look like this:
You’ll notice that the Daemon ThreadsIn computer science, a
Python If a program is running Let’s look a little more closely at the output of your program above. The last two lines are the interesting bit. When you run the program, you’ll notice that there is a pause (of about 2 seconds) after This pause is Python waiting for the non-daemonic thread to complete. When your Python program ends, part of the shutdown process is to clean up the threading routine. If you look at the source for Python So your program waits to exit because the thread itself is waiting in a sleep. As soon as it has completed and printed the message, Frequently, this behavior is what you want, but there are other options available to us. Let’s first repeat the program with a
When you run the program now, you should see this output:
The difference here is that the final line of the output is missing. join() a ThreadDaemon threads are handy, but what about when you want to wait for a thread to stop? What about when you want to do that and not exit your program? Now let’s go back to your original program and look at that commented out line twenty: To tell one thread to wait for another thread to finish, you call Did you test this on the code with the daemon thread or the regular thread?
It turns out that it doesn’t matter. If you Working With Many ThreadsThe example code so far has only been working with two threads: the main thread and one you started with the Frequently, you’ll want to start a number of threads and have them do interesting work. Let’s start by looking at the harder way of doing that, and then you’ll move on to an easier method. The harder way of starting multiple threads is the one you already know:
This code uses the same mechanism you saw above to start a thread, create a Running this code multiple times will likely produce some interesting results. Here’s an example output from my machine:
If you walk through the output carefully, you’ll see all three threads getting started in the order you might expect, but in this case they finish in the opposite order! Multiple runs will produce different orderings. Look for the The order in which threads are run is determined by the operating system and can be quite hard to predict. It may (and likely will) vary from run to run, so you need to be aware of that when you design algorithms that use threading. Fortunately, Python gives you several primitives that you’ll look at later to help coordinate threads and get them running together. Before that, let’s look at how to make managing a group of threads a bit easier. Using a ThreadPoolExecutorThere’s an easier way to start up a group of threads than the one you saw above. It’s called a The easiest way to create it is as a context manager, using
the Here’s the
The code creates a The end
of the Running your corrected example code will produce output that looks like this:
Again, notice how Race ConditionsBefore you move on to some of the other features tucked away in Python Once you’ve seen what a race condition is and looked at one happening, you’ll move on to some of the primitives provided by the standard library to prevent race conditions from happening. Race conditions can occur when two or more threads access a shared piece of data or resource. In this example, you’re going to create a large race condition that happens every time, but be aware that most race conditions are not this obvious. Frequently, they only occur rarely, and they can produce confusing results. As you can imagine, this makes them quite difficult to debug. Fortunately, this race condition will happen every time, and you’ll walk through it in detail to explain what is happening. For this example, you’re going to write a class that updates a database. Okay, you’re not really going to have a database: you’re just going to fake it, because that’s not the point of this article. Your
In this case, reading from the database just means copying Here’s how you’ll use this
The program creates a
In the usage above, Since each thread runs
You might have expected that to happen, but let’s look at the details of what’s really going on here, as that will make the solution to this problem easier to understand. One ThreadBefore you dive into this issue with two threads, let’s step back and talk a bit about some details of how threads work. You won’t be diving into all of the details here, as that’s not important at this level. We’ll also be simplifying a few things in a way that won’t be technically accurate but will give you the right idea of what is happening. When you tell your The result of this is that each of the threads in the pool will call Each thread is going to have a reference to the same When the thread starts running Now you can start walking through what happens if you run the program above with a single thread and a single call to The image below steps through the execution of The diagram is laid out so that time increases as you move from top to bottom. It begins when When Next When So far, so good. You ran Two ThreadsGetting back to the race condition, the two threads will be running concurrently but not at the same time. They will each have their own version of The program starts with
When
When
The two threads have interleaving access to a single shared object, overwriting each other’s results. Similar race conditions can arise when one thread frees memory or closes a file handle before the other thread is finished accessing it. Why This Isn’t a Silly ExampleThe example above is contrived to make sure that the race condition happens every time you run your program. Because the operating system can
swap out a thread at any time, it is possible to interrupt a statement like The details of how this happens are quite interesting, but not needed for the rest of this article, so feel free to skip over this hidden section. The code above isn’t quite as out there as you might originally have thought. It was designed to force a race condition every time you run it, but that makes it much easier to solve than most race conditions. There are two things to keep in mind when thinking about race conditions:
Let’s look at this in detail. The REPL below shows a function that takes a parameter and increments it: >>>
The REPL example uses We’re stopping here for a specific reason. This is the point in As
you learned above, the operating system can swap threads at any time. You’ve walked down this listing to the statement marked Technically, this example won’t have a race condition because It’s rare to get a race condition like this to occur, but remember that an infrequent event taken over millions of iterations becomes likely to happen. The rarity of these race conditions makes them much, much harder to debug than regular bugs. Now back to your regularly scheduled tutorial! Now that you’ve seen a race condition in action, let’s find out how to solve them! Basic Synchronization Using LockThere are a number of ways to avoid or solve race conditions. You won’t look at all of them here, but there are a couple that are used frequently. Let’s start with
To solve your race condition above, you need to find a way to allow only one thread at a time into the read-modify-write section of your code. The most common way to do this is called A The basic functions to do this are Fortunately, Python’s Let’s look at the
Other than adding a bunch of debug logging so you can see the locking more clearly, the big change here is to add a member called It’s worth noting here that the thread running this function will hold on to that If you run this version with logging set to warning level, you’ll see this:
Look at that. Your program finally works! You can turn on full logging by setting the level to
Running this program with
In this output you can see Many of the examples in
the rest of this article will have DeadlockBefore you move on, you should look at a common problem when using
When the program calls
The first situation happens sometimes, but using a The design issue can be a bit trickier in some languages.
Thankfully, Python threading has a second object, called
Producer-Consumer ThreadingThe Producer-Consumer Problem is a standard computer science problem used to look at threading or process
synchronization issues. You’re going to look at a variant of it to get some ideas of what primitives the Python For this example, you’re going to imagine a program that needs to read messages from a network and write them to disk. The program does not request a message when it wants. It must be listening and accept messages as they come in. The messages will not come in at a regular pace, but will be coming in bursts. This part of the program is called the producer. On the other side, once you have a message, you need to write it to a database. The database access is slow, but fast enough to keep up to the average pace of messages. It is not fast enough to keep up when a burst of messages comes in. This part is the consumer. In between the producer and the consumer, you will create a That’s the basic layout. Let’s look at a
solution using Producer-Consumer Using LockSince this is an article about Python The general design is that there is a
To generate a fake message, the The On the other side of the
The Before you look at the really interesting part, the
This should look fairly familiar as it’s close to the Remember that you can turn on
It can be worthwhile to walk through the Now let’s take a look at the
Woah! That’s a lot of code. A pretty high percentage of that is just logging statements to make it easier to see what’s happening when you run it. Here’s the same code with all of the logging statements removed:
That seems a bit more manageable. The
Once the Before you go on to Here’s the answer. As soon as the Moving on to Let’s run the code that has logging set to
At first, you might find it odd that the producer gets two messages before the consumer even runs. If you look back at the When the The operating system can swap threads at any time, but it generally lets each thread have a reasonable amount of time to run before swapping it out. That’s why the Once a thread is blocked, however, the operating system will always swap it out and find a different thread to run. In this case, the only other thread with anything to do is the The Notice that the first message was While it works for this limited test, it is not a great solution to the producer-consumer problem in general because it only allows a single value in the pipeline at a time. When the Let’s move on to a better way to solve this problem, using a Producer-Consumer Using QueueIf you want to be able to handle more than one value in the pipeline at a time, you’ll need a data structure for the pipeline that allows the number to grow and shrink as data backs up from the Python’s standard library has a Let’s start with the The triggering of the event can be many things. In this example, the main thread will simply sleep for a while and then
The only changes here are the creation of the The
It now will loop until it sees that the event was set on line 3. It also no longer puts the
While you got to take out the code related to the Making
sure the queue is empty before the consumer finishes prevents another fun issue. If the This happens if the If
that happens, it’s possible for the consumer to wake up and exit with the queue still completely full. The The rest of the The
You can see that If you give a positive number for
The core devs who wrote the standard library knew that a Running this program looks like the following:
If you read through the output in my example, you can see some interesting things happening. Right at the top, you can see the The
This is how you know that the fifth message hasn’t made it into the As the program starts to wrap up, can you see the main thread generating the Try playing with different queue sizes and calls to This is a much better solution to the producer-consumer problem, but you can simplify it even more. The Here’s what the final code looks like using
That’s easier to read and shows how using Python’s built-in primitives can simplify a complex problem.
Threading ObjectsThere are a few more primitives offered by the Python SemaphoreThe first Python The internal counter is incremented when you call The next special property is that if a thread calls Semaphores are frequently used to protect a resource that has a limited capacity. An example would be if you have a pool of connections and want to limit the size of that pool to a specific number. TimerA
You
start the If you want to stop a A BarrierA Remember that threads are scheduled by the operating system so, even though all of the threads are released simultaneously, they will be scheduled to run one at a time. One use for a Conclusion: Threading in PythonYou’ve now seen much of what Python If you’d like to explore other options for concurrency in Python, check out Speed Up Your Python Program With Concurrency. If you’re interested in doing a deep dive on the Whatever you do, you now have the information and confidence you need to write programs using Python threading! Special thanks to reader JL Diaz for helping to clean up the introduction. Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Threading in Python Can you restart a thread in Python?Python threads cannot be restarted or reused. In fact, this is probably a limitation of the capabilities of threads provided by the underlying operating system. Once a thread has terminated you cannot call the start() method on it again to reuse it.
How many times a thread can be started in Python?Due to a global interpreter lock (GIL), Python threads are restricted to an execution model that only allows one thread to execute in the interpreter at any given time.
Why we Cannot start thread twice?according to thread life cycle, once thread is 'dead' you can not restart it. You only can start new thread invoking start() method. Thread can be bought to Running state from Runnable state not from Dead state.
Can we call run method twice?Multiple invocation: In Java's multi-threading concept, another most important difference between start() and run() method is that we can't call the start() method twice otherwise it will throw an IllegalStateException whereas run() method can be called multiple times as it is just a normal method calling.
|