求救:线程池问题

求救:线程池问题

问题:
程序有时候运行到一半就挂在那儿了,有时候又运行的没问题。
希望知道线程同步的高手帮帮忙,看看问题在哪儿。

代码如下:

import threading
import random
import time, sys

class UThread(threading.Thread):   ##运行任务函数的线程类

    def __init__(self, event):
        threading.Thread.__init__(self)
        self.event = event
        self.fun = None
        self.isbusy = False
        self.setDaemon(1)

    def isBusy(self):
        return self.isbusy

    def setFun(self, fun,*args, **kargs): ## 设定任务函数和参数
        self.isbusy = True
        self.fun = fun
        self.args= args
        self.kargs = kargs

    def run(self):
        while True:
            self.event.wait()           ##等待run的信号
            self.event.clear()

            if self.fun:
                self.fun(*self.args, **self.kargs) ##运行任务函数
                self.fun = None                    ##运行完后的清理

            self.isbusy = False                    ##可以分配新的任务了


class ThreadPool(threading.Thread):

    def __init__(self, nThread):
        threading.Thread.__init__(self)
        self.nThread = nThread                  ##创建nThread个线程
        self.eventList  = []                    ##每个线程都有一个相应的事件来控制它run和wait
        self.threadList = []                    ##线程列表
        self.taskList = []                      ##任务列表

    def addTask(self, fun, *args, **kargs):
        L = [fun, args, kargs]                  ##任务格式:[函数,列表参数, 字典参数]
        self.taskList.append(L)

    def taskScheduler(self):   ##任务调度, 如果任务列表中还有任务,就在线程列表中找不忙的线程
        if len(self.taskList): ##分配给它函数及参数,在调用Event的set方法.此时线程中的run函数
            for i in range(self.nThread): ##停在wait()方法处,接到set信号后就可以继续运行
                if self.threadList[i].isBusy() == False:
                    try:
                        L = self.taskList.pop(0)
                    except IndexError:
                        break
                    self.threadList[i].setFun(L[0], *L[1], **L[2])            
                    self.eventList[i].set()

        else:
            for i in range(self.nThread):
                if self.threadList[i].isBusy():
                    return ##所有任务完成了,线程都不是busy的,就结束程序
            sys.exit(0)              
               
        
    def createThread(self):  ##创建nThread个线程,并为每个线程建一个Event
        for i in range(self.nThread):
            event = threading.Event()
            self.eventList.append(event)
            self.threadList.append(UThread(event))
        for i in range(self.nThread):
            self.threadList[i].start()

    def run(self):
        self.createThread()
        while True:
            self.taskScheduler() ##每隔1秒种调用一次任务调度函数
            time.sleep(1)
        

def test():        
    def fun(t, msg):
        time.sleep(t)
        print msg

    pool = ThreadPool(7)
    pool.start()
    for i in range(50): ##50个任务,7个线程
        pool.addTask(fun, random.randint(1, 20), '%d msg'%i)

if __name__ == "__main__":
    test()
我测了一下:

1484 00093 msg
Traceback (most recent call last):
  File "t.py", line 56, in taskScheduler
    L = self.taskList.pop(0)
IndexError: pop from empty list
None
3908 00087 msg
1484 00099 msg
2156 00097 msg
2892 00088 msg


使用 import traceback; traceback.print_exc();

使用thread.jion() 来等待线程结束.
为什么你的结果是
3908 0087 msg。。。
是改了线程数和任务数量么?100个线程,4000个任务?

子线程中的run()函数都是while True 的无限循环,因此不能在ThreadPool中用thread.jion方法来等待线程结束。

那个pop的异常已经被捕获了,异常发生说明任务以经全部分配完了,应该不会导致程序挂在那儿没有响应。
不好意思, 我把线程的ID,打出来了.   
print thread.get_ident(), msg


"挂在那儿": 是不是死锁了, 程序不能结束了.
我测了好几次,都正常结束了.
用笨办法, 多写print 作调试吧, ^_^.