Time.Sleep -- Sleeps Thread or Process

time.sleep -- sleeps thread or process?

It blocks the thread. If you look in Modules/timemodule.c in the Python source, you'll see that in the call to floatsleep(), the substantive part of the sleep operation is wrapped in a Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS block, allowing other threads to continue to execute while the current one sleeps. You can also test this with a simple python program:

import time
from threading import Thread

class worker(Thread):
def run(self):
for x in xrange(0,11):
print x
time.sleep(1)

class waiter(Thread):
def run(self):
for x in xrange(100,103):
print x
time.sleep(5)

def run():
worker().start()
waiter().start()

Which will print:

>>> thread_test.run()
0
100
>>> 1
2
3
4
5
101
6
7
8
9
10
102

Time.sleep seems to be blocking main thread, not just child thread?

Sleep calls only block the thread in which they're called. Printing anything in the main thread immediately after the call to curr_thread.start() will prove this to you.

However, if you interrupt your code (Ctrl-C), you'll see a useful stack trace. The last call is inside the threading module's _shutdown() method, which appears to be waiting for all non-daemon threads to finish.

t = _pickSomeNonDaemonThread()
while t:
t.join()
t = _pickSomeNonDaemonThread()

And reading the documentation for the threading module, you can see that: "The entire Python program exits when no alive non-daemon threads are left." So, because you've done curr_thread.daemon = False, you're forcing the main thread to wait for this thread to finish first.

I should point out, though, that threads inherit the "daemon-ness" of their parents. Since the main thread is never a daemon thread, you could have left off the curr_thread.daemon = False, and you'd get the same behavior.

using time.sleep() in Thread python3

The threading.Thread() creates new thread and t1.start() just dispatch it.

This code:

for num in range(0,10):
t1 = threading.Thread(target=test1, args=(num,))
t2 = threading.Thread(target=test2, args=(num,))
t1.start()
t2.start()

actually creates and start 2 new threads per iteration. At the end you have 20 threads + master thread.

Also when you start thread you should wait until it ends or run it as daemon thread. With daemon thread you are saying I don't care what you do and when you end.

Basic thread usage can looks like this:

import threading

def do_stuff():
print("Stuff on thread {}".format(threading.get_ident()))

print("Main thread {}".format(threading.get_ident()))
t = threading.Thread(target=do_stuff) # Specify what should be running in new thread
t.start() # Dispatch thread
t.join() # Wait until the thread is done

Note: threading.get_ident() gives you unique identifier of the thread where this function is called.

Now from you example if you want start 2 independent threads you can do this:

import threading
import time

def test2():
for count in range(0, 10):
if count == 8:
print("test2: sleep for 4 sec")
time.sleep(3.0)
print("test2: thread = {}".format(count))

def test1():
for count in range(0, 10):
if count == 5:
print("test 1: sleep for 5 sec")
time.sleep(3.0)
print("test1: thread = {}".format(count))

t1 = threading.Thread(target=test1)
t2 = threading.Thread(target=test2)
t1.start()
t2.start()
t1.join()
t2.join()

But you might want to synchronize those threads and send them some item at the "same" time.

import threading

# Create threads
t1 = threading.Thread(target=test1)
t2 = threading.Thread(target=test2)

# Run threads
t1.start()
t2.start()

# Go through some list or whatever
for num in range(0,10):
# send num to t1
# send num to t2
# wait for t1 and t2
pass

# Wait until threads are finished with their jobs
t1.join()
t2.join()

For sending value to other thread we can user queue.Queue. You can safely put there value in one thread and second thread can read it or wait until there is something (or multiple thread can write and multiple thread can read).

import threading
import time
import queue

def test2(q):
while True:
count = q.get() # Get data from the q2 queue
if count == 8:
print("test2: sleep for 4 sec")
time.sleep(3.0)
print("test2: thread = {}".format(count))

def test1(q):
while True:
count = q.get() # Get data from the q1 queue
if count == 5:
print("test 1: sleep for 5 sec")
time.sleep(3.0)
print("test1: thread = {}".format(count))

# Creates queues
q1 = queue.Queue()
q2 = queue.Queue()

# Create threads
t1 = threading.Thread(target=test1, args=(q1, ))
t2 = threading.Thread(target=test2, args=(q2, ))

# Run threads
t1.start()
t2.start()

# Go through some list or whatever
for num in range(0, 10):
# send num to t1
q1.put(num)
# send num to t2
q2.put(num)
# wait for t1 and t2
# ???

# Wait until threads are finished with their jobs
t1.join()
t2.join()

Oh wait... how can we know that threads are done with their work and we can send another value? Well we can use Queue again. Create new pair and sending e.g. True at the end of the test? function and then wait read in main loop from those queues. But for sending state information we should use threading.Event.

import threading
import time
import queue

def test2(q, e):
while True:
count = q.get() # Get data from the q2 queue
if count == 8:
print("test2: sleep for 4 sec")
time.sleep(3.0)
print("test2: thread = {}".format(count))
e.set() # Inform master the processing of given value is done

def test1(q, e):
while True:
count = q.get() # Get data from the q1 queue
if count == 5:
print("test 1: sleep for 5 sec")
time.sleep(3.0)
print("test1: thread = {}".format(count))
e.set() # Inform master the processing of given value is done

# Creates queues
q1 = queue.Queue()
q2 = queue.Queue()

# Create events
e1 = threading.Event()
e2 = threading.Event()

# Create threads
t1 = threading.Thread(target=test1, args=(q1, e1))
t2 = threading.Thread(target=test2, args=(q2, e2))

# Run threads
t1.start()
t2.start()

# Go through some list or whatever
for num in range(0, 10):
# send num to t1
q1.put(num)
# send num to t2
q2.put(num)
# wait for t1
e1.wait()
# wait for t2
e2.wait()

# Wait until threads are finished with their jobs
t1.join()
t2.join()

Now we are almost there but the script never ends. It's because the test? functions (threads) waits in infinite loop for data (from queues q1/q2). We need some way how to tell them "Ok, that's all folks". For that we can say None value in queues means end. The result following:

import threading
import time
import queue

def test2(q, e):
while True:
count = q.get() # Get data from the q2 queue
if count is None: # Exit on None value
return
if count == 8:
print("test2: sleep for 4 sec")
time.sleep(3.0)
print("test2: thread = {}".format(count))
e.set() # Inform master the processing of given value is done

def test1(q, e):
while True:
count = q.get() # Get data from the q1 queue
if count is None: # Exit on None value
return
if count == 5:
print("test 1: sleep for 5 sec")
time.sleep(3.0)
print("test1: thread = {}".format(count))
e.set() # Inform master the processing of given value is done

# Creates queues
q1 = queue.Queue()
q2 = queue.Queue()

# Create events
e1 = threading.Event()
e2 = threading.Event()

# Create threads
t1 = threading.Thread(target=test1, args=(q1, e1))
t2 = threading.Thread(target=test2, args=(q2, e2))

# Run threads
t1.start()
t2.start()

# Go through some list or whatever
for num in range(0, 10):
# send num to t1
q1.put(num)
# send num to t2
q2.put(num)
# wait for t1
e1.wait()
# wait for t2
e2.wait()

# Inform threads to exit
q1.put(None)
q2.put(None)

# Wait until threads are finished with their jobs
t1.join()
t2.join()

Note: instead of using parameters in threads "main" functions you can use global variables, because global variables or class attributes are shared across all threads. But usually it is bad practice.


Be aware of gotchas coming with threading, for example exception handling is not so easy. Imagine that function test1 raises exception before calling e.set(). Then the master thread never ends waiting on e1.wait().

Also CPython (the most common implementation of the Python) has something called GIL, which basically (with some exceptions) allows running only 1 thread at a time and the others are sleeping.


Threading documentation

Queue documentation

Difference between wait() vs sleep() in Java

A wait can be "woken up" by another thread calling notify on the monitor which is being waited on whereas a sleep cannot. Also a wait (and notify) must happen in a block synchronized on the monitor object whereas sleep does not:

Object mon = ...;
synchronized (mon) {
mon.wait();
}

At this point the currently executing thread waits and releases the monitor. Another thread may do

synchronized (mon) { mon.notify(); }

(on the same mon object) and the first thread (assuming it is the only thread waiting on the monitor) will wake up.

You can also call notifyAll if more than one thread is waiting on the monitor – this will wake all of them up. However, only one of the threads will be able to grab the monitor (remember that the wait is in a synchronized block) and carry on – the others will then be blocked until they can acquire the monitor's lock.

Another point is that you call wait on Object itself (i.e. you wait on an object's monitor) whereas you call sleep on Thread.

Yet another point is that you can get spurious wakeups from wait (i.e. the thread which is waiting resumes for no apparent reason). You should always wait whilst spinning on some condition as follows:

synchronized {
while (!condition) { mon.wait(); }
}

Does time.sleep() stop all executions?

from time import time

prev = time()
while True:
now = time()
if now - prev > 3:
print 'report'
prev = now
else:
pass
# runs

time.sleep seems to block other threads

You are invoking hello on the main thread by using hello() this is a function call (because of the ()), not a function reference. The reference (name) is just hello.

Maybe try:

threading.Thread(target=hello).start()

interaction of time.sleep with threading.Lock

Change your code to this and see what's happening:

import threading
import time

LOCK = threading.Lock()

class Printer(threading.Thread):
def __init__(self, *args, **kwargs):
super(Printer, self).__init__(*args, **kwargs)
self.daemon = True
self.i = 0

def run(self):
while True:
with LOCK:
print(self.i)
self.i += 1
time.sleep(1)

raw_input('press enter to start thread\n')
Printer().start()
raw_input('press enter to pause thread\n')
print('acquiring...')
LOCK.acquire()
print('acquired')
raw_input('press enter to resume thread\n')
LOCK.release()
raw_input('press enter to exit program\n')
print('bye!')

when your code tries to run LOCK.acquire() I think a race begins between with LOCK and LOCK.acquire() and the thread wins the game most of time and acquires LOCK for 1 second. But in the first method, when Printer() is waiting for 1 second, the Main thread acquires LOCK without any problem because it's free. I hope you get it. sorry for my language :))



Related Topics



Leave a reply



Submit