进程,线程与线程池(1)

来源:互联网 发布:java.nio.file.files 编辑:程序博客网 时间:2024/05/18 02:49

传统方法:创建一个新的线程,由该线程执行任务,任务执行完毕后线程退出——即时创建,即时销毁

如果提交给线程的任务是执行时间较短,执行次数频繁,那么不断销毁和不断创建的开销则是不可忽略的。

线程池采用预创建技术,在应用程序启动之后,立即创建一定数量的线程,放入空闲队列中,这些线程处于阻塞状态,不消耗CPU,占用较小的内存。当任务到来。缓冲池选择一个空闲线程,把任务传入此线程中运行,当以创建的线程都在处理任务时,缓冲池自动创建一定数量的新线程,用于处理更多的任务。任务执行完毕后,线程不退出,而是继续在池中等待下一次任务。当系统比较空闲时,大部分线程处于阻塞状态,线程池自动销毁一部分线程,回收系统资源。这样线程创建和销毁的开销分到了多个任务上,执行次数越多,每个任务所分担到的线程本身的开销越小。

线程到任务队列里面取任务,执行完成后通知系统,然后继续去队列中取下一个任务,直至任务队列取空,退出线程。

一般线程池具备以下几个组成部分:1.线程池管理器 2.工作线程 3.任务接口 4.任务队列

线程池管理器用于创建并管理线程池,工作线程是线程池中实际执行的线程,将线程执行的任务抽象成任务接口,从而使线程池与具体任务无关,线程池具体实现是可能是队列,链表等数据结构

具体步骤如下:

1.创建1个 queue.Queue() 的实例,使用数据(任务及其参数)进行填充

2.将经过填充的实例传给线程类,后者继承于 threading.Thread

3.生成守护线程池

4.每次从队列中取出并删除一个项目,得到任务及其参数,执行

5.一个项目完成以后,使用queue.task_done()向任务已经完成的队列发送一个信号

6.对队列执行join操作,等到队列为空,退出主程序


Q:Python中的Queue对象提供了对线程同步的支持,是线程安全的,使用Queue对象可以实现多个生产者和多个消费者组成的FIFO队列,生产者依次存入,消费者依次取出

*args:当函数的参数不确定是可以使用 *args 和 **kwargs,*args没有key值,用于元组,**kwargs有key值,用于字典

def test_var_args(farg,*args):

    for arg in args:

        print  " another arg",arg

def test_var_kwargs(farg,*kwargs):

    for key in kwargs:

        print "another keyword arg: %s: %s" % (key,kwargs[key])


test_var_args(1,'two',3')

test_var_kwargs(farg=1,myarg2="two",myarg3=3)

Python queue模块 定义了下列类和异常:

类1 class queue.Queue(maxsize=0)

类2 class queue.LifoQueue(maxsize=0)

类3 class queue.PriorityQueue(maxsize=0)

异常 exception queue.Empty 在空的对象上调用get()会抛出此异常

异常 evception queue.Full 在满的对象上调用put()会抛出此异常


queue.task_done() 由队列的消费者线程调用,告诉队列该任务已经处理完毕

queue.join() 阻塞调用线程,数据被加入队列,未完成的任务数就会增加,当消费者线程调用task_done(),意味着有消费者取得任务并完成,未完成的任务数就会减少,当未完成的任务数降为0,join()解除阻塞

Thread中,join()方法的作用是调用线程,等待线程完成后才能向下进行。

创建线程的方式:1定义一个类集成Thread类 2覆盖Thread类中的run方法 3直接创建Thread的子类对象线程 4调用start方法开启线程并调用线程的任务run方法执行


threading模块中的Thread对象,run方法和start方法都是从Thread继承而来,start()方法用于启动线程,不能被重复调用,run()方法将在线程开启后执行

start()   -->   start0()   -->   run()

一个简单的线程池代码

thread_pool.py

import threading
import time
import queue
 
class WorkManager(object):
    def __init__(self,workNum=100,threadNum=2):
        self.workQueue=queue.Queue()
        self.threads=[]
        self.__init_work_queue(workNum)
        self.__init_thread_pool(threadNum)

    def __init_thread_pool(self,threadNum):
        for i in range(threadNum):
            self.threads.append(Work(self.workQueue))

    def __init_work_queue(self,jobsNum):
        for i in range(jobsNum):
            self.add_job(do_job,i)

    def add_job(self,func,*args):
        #任务入队
        self.workQueue.put((func,list(args)))

    def wait_allcomplete(self):
        for item in self.threads:
            #检查线程是否在运行中
            if item.isAlive():
                item.join()
      
class Work(threading.Thread):
    def __init__(self,workQueue):
        threading.Thread.__init__(self)
        self.workQueue=workQueue
        #启动线程
        self.start()   

     #run通常需要重写,编写代码实现需要的功能   
    def run(self):
        # 死循环,让创建的线程在一定条件下退出
        while True:
            try:
                #任务异步出队,Queue内部实现了同步机制
                do, args=self.workQueue.get(block=False)
                do(args)
                self.workQueue.task_done()
            except:
                print ('Get out of this Thread')
                break
                    
def do_job(args):
    time.sleep(0.1) #模拟处理时间
    print (threading.current_thread(),list(args))


if __name__=='__main__':
    start=time.time()
    work_manager=WorkManager(10000,10)
    work_manager.wait_allcomplete()
    end=time.time()
    print ('cost %s' % (end-start))

0 0
原创粉丝点击