终止线程:Python

时间:2013-01-10 22:27:57

标签: python multithreading python-multithreading

在下面的示例中,如果多次执行程序,则每次使用新ID生成一个新线程。 1.如何在任务完成时终止所有线程? 2.如何为线程分配名称/ ID?

import threading, Queue 

THREAD_LIMIT = 3                 
jobs = Queue.Queue(5)           # This sets up the queue object to use 5 slots 
singlelock = threading.Lock()   # This is a lock so threads don't print trough each other 

# list  
inputlist_Values = [ (5,5),(10,4),(78,5),(87,2),(65,4),(10,10),(65,2),(88,95),(44,55),(33,3) ] 

def DoWork(inputlist): 
    print "Inputlist received..."
    print inputlist 

    # Spawn the threads 
    print "Spawning the {0} threads.".format(THREAD_LIMIT) 
    for x in xrange(THREAD_LIMIT): 
        print "Thread {0} started.".format(x) 
        # This is the thread class that we instantiate. 
        worker().start() 

    # Put stuff in queue 
    print "Putting stuff in queue"
    for i in inputlist: 
        # Block if queue is full, and wait 5 seconds. After 5s raise Queue Full error. 
        try: 
            jobs.put(i, block=True, timeout=5) 
        except: 
            singlelock.acquire() 
            print "The queue is full !"
            singlelock.release() 

    # Wait for the threads to finish 
    singlelock.acquire()        # Acquire the lock so we can print 
    print "Waiting for threads to finish."
    singlelock.release()        # Release the lock 
    jobs.join()                 # This command waits for all threads to finish. 

class worker(threading.Thread): 
    def run(self): 
        # run forever 
        while 1: 
            # Try and get a job out of the queue 
            try: 
                job = jobs.get(True,1) 
                singlelock.acquire()        # Acquire the lock 
                print self
                print "Multiplication of {0} with {1} gives {2}".format(job[0],job[1],(job[0]*job[1]))         
                singlelock.release()        # Release the lock 
                # Let the queue know the job is finished. 
                jobs.task_done() 
            except: 
                break           # No more jobs in the queue 


def main():    
    DoWork(inputlist_Values)

2 个答案:

答案 0 :(得分:1)

  

如何在任务完成时终止所有线程?

您可以将THREAD_LIMIT个标记值(例如None)放在队列的末尾,如果线程看到它,则退出线程的run()方法。

在主线程退出时,所有非守护程序线程都会被连接,因此如果任何线程处于活动状态,程序将继续运行。守护程序线程在程序出口处终止。

  

如何为线程分配名称/ ID?

您可以通过将名称传递给构造函数或直接更改.name来指定名称。

线程标识符.ident是一个只读属性,在活动线程中是唯一的。如果一个线程退出而另一个线程启动,它可能会被重用。


您可以使用multiprocessing.dummy.Pool重写代码,该代码提供与multiprocessing.Pool相同的接口,但使用线程而不是进程:

#!/usr/bin/env python
import logging
from multiprocessing.dummy import Pool

debug = logging.getLogger(__name__).debug

def work(x_y):
    try:
        x, y = x_y # do some work here
        debug('got %r', x_y)
        return x / y, None
    except Exception as e:
        logging.getLogger(__name__).exception('work%r failed', x_y) 
        return None, e

def main():
    logging.basicConfig(level=logging.DEBUG,
        format="%(levelname)s:%(threadName)s:%(asctime)s %(message)s")

    inputlist = [ (5,5),(10,4),(78,5),(87,2),(65,4),(10,10), (1,0), (0,1) ]
    pool = Pool(3)
    s = 0.
    for result, error in pool.imap_unordered(work, inputlist):
        if error is None:
           s += result
    print("sum=%s" % (s,))
    pool.close()
    pool.join()

if __name__ == "__main__":
   main()

Output

DEBUG:Thread-1:2013-01-14 15:37:37,253 got (5, 5)
DEBUG:Thread-1:2013-01-14 15:37:37,253 got (87, 2)
DEBUG:Thread-1:2013-01-14 15:37:37,253 got (65, 4)
DEBUG:Thread-1:2013-01-14 15:37:37,254 got (10, 10)
DEBUG:Thread-1:2013-01-14 15:37:37,254 got (1, 0)
ERROR:Thread-1:2013-01-14 15:37:37,254 work(1, 0) failed
Traceback (most recent call last):
  File "prog.py", line 11, in work
    return x / y, None
ZeroDivisionError: integer division or modulo by zero
DEBUG:Thread-1:2013-01-14 15:37:37,254 got (0, 1)
DEBUG:Thread-3:2013-01-14 15:37:37,253 got (10, 4)
DEBUG:Thread-2:2013-01-14 15:37:37,253 got (78, 5)
sum=78.0

答案 1 :(得分:0)

除非你告诉他们停止,否则线程不会停止。

我的建议是在stop子类中添加Thread变量,并在运行循环中检查此变量是否为True(而不是while 1: )。

一个例子:

class worker(threading.Thread): 
    def __init__(self):
         self._stop = False

    def stop(self):
         self._stop = True

    def run(self): 
        # run until stopped 
        while not self._stop:                 
            # do work

然后,当您的程序退出时(无论出于何种原因),您必须确保在所有工作线程上调用stop方法。

关于您的第二个问题,是否未向您的name子类添加Thread变量?