[Python编程(第4版)].(Programming.Python.4th.Edition).Mark.Lutz.文字版

(yzsuai) #1

thread.start_new_thread(producer, (i,))
time.sleep(((numproducers-1) * nummessages) + 1)
print('Main thread exit.')


Before I show you this script’s output, I want to highlight a few points in its code.


Arguments versus globals


Notice how the queue is assigned to a global variable; because of that, it is shared by
all of the spawned threads (all of them run in the same process and in the same global
scope). Since these threads change an object instead of a variable name, it would work
just as well to pass the queue object in to the threaded functions as an argument—the
queue is a shared object in memory, regardless of how it is referenced (see
queuetest2.py in the examples tree for a full version that does this):


dataQueue = queue.Queue() # shared object, infinite size

def producer(idnum, dataqueue):
for msgnum in range(nummessages):
time.sleep(idnum)
dataqueue.put('[producer id=%d, count=%d]' % (idnum, msgnum))

def consumer(idnum, dataqueue): ...

if __name__ == '__main__':
for i in range(numproducers):
thread.start_new_thread(producer, (i, dataQueue))
for i in range(numproducers):
thread.start_new_thread(producer, (i, dataQueue))

Program exit with child threads


Also notice how this script exits when the main thread does, even though consumer
threads are still running in their infinite loops. This works fine on Windows (and most
other platforms)—with the basic _thread module, the program ends silently when the
main thread does. This is why we’ve had to sleep in some examples to give threads time
to do their work, but is also why we do not need to be concerned about exiting while
consumer threads are still running here.


In the alternative threading module, though, the program will not exit if any spawned
threads are running, unless they are set to be daemon threads. Specifically, the entire
program exits when only daemon threads are left. Threads inherit a default initial dae-
monic value from the thread that creates them. The initial thread of a Python program
is considered not daemonic, though alien threads created outside this module’s control
are considered daemonic (including some threads created in C code). To override in-
herited defaults, a thread object’s daemon flag can be set manually. In other words,
nondaemon threads prevent program exit, and programs by default do not exit until
all threading-managed threads finish.


206 | Chapter 5: Parallel System Tools

Free download pdf