博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python中threading多线程
阅读量:6924 次
发布时间:2019-06-27

本文共 3959 字,大约阅读时间需要 13 分钟。

python中有两个处理多线程的模块thread和threading。其中thread提供了多线程底层支持的模块,以低级原始的发那个是来处理和控制线程,使用起来较为复杂;而threading基于thread进行包装,将线程操作对象化。

最基础的的多线程

我们先看一个最最基础的多线程例子

import threadingimport timeclass test(threading.Thread):    def __init__(self,name,delay):        threading.Thread.__init__(self)        self.name = name        self.delay = delay    def run(self):        print "%s is running"%self.name        for x in range(self.delay):           time.sleep(1)           print "%s is saying hello %d"%(self.name,x)def main():    t1 = test('Thread 1',3)    t2 = test('Thread 2',2)    t1.start()    t2.start()if __name__ == '__main__':    main()    print "End of main"

输出结果如下:

Thread 1 is running

 End of mainThread 2 is running
Thread 1 is saying hello 0
Thread 2 is saying hello 0
Thread 1 is saying hello 1
Thread 2 is saying hello 1
Thread 1 is saying hello 2

可以看出Thread1 和Thread2基本上轮流执行的,这就是多线程的好处,否则如果顺序执行2个程序会需要2倍的时间。

start是对thread的run()的封装,在调用start()的时候,会执行run()函数。

如果把代码中的一段改成下面这样呢?

def main():    t1 = test('Thread 1',3)    t2 = test('Thread 2',2)    t1.start()    print "wait for thread1 end"    t1.join()    t2.start()

输出结果为:

wait for thread1 endThread 1 is running

Thread 1 is saying hello 0
Thread 1 is saying hello 1
Thread 1 is saying hello 2
End of mainThread 2 is running
Thread 2 is saying hello 0
Thread 2 is saying hello 1

从上面可以看出,调用了t1.join()后,t2会一直等到t1执行完毕才会开始执行。

 

使用Queue进行多线程编程

使用线程队列

如前所述,当多个线程需要共享数据或者资源的时候,可能会使得线程的使用变得复杂。线程模 块提供了许多同步原语,包括信号量、条件变量、事件和锁。当这些选项存在时,最佳实践是转而关注于使用队列。相比较而言,队列更容易处理,并且可以使得线 程编程更加安全,因为它们能够有效地传送单个线程对资源的所有访问,并支持更加清晰的、可读性更强的设计模式。

import threadingimport timeimport Queueimport urllib2import osclass test(threading.Thread):    def __init__(self,queue):        threading.Thread.__init__(self)        self.queue = queue    def run(self):        while 1:            url = self.queue.get()            print self.name+"begin download"+url+"..."            self.download(url)            self.queue.task_done()            print self.name+"download completed"    def download(self,url):        urlHandle = urllib2.urlopen(url)        with open(os.path.basename(url)+".html","wb")as fp:            while 1:                contents=urlHandle.read(1024)                if not contents:                    break                else:                    fp.write(contents)def main():    ulrs = ["http://wiki.python.org/moin/Webprograming",    "https://www.baidu.com",    "http://wiki.python.org/moin/Documendation"]    q = Queue.Queue(5)    for each in ulrs:      q.put(each)    for i in range(5):        t = test(q)        t.setDaemon(True)        t.start()    q.join()if __name__ == '__main__':    main()

 join()

保持阻塞状态,直到处理了队列中的所有项目为止。在将一个项目添加到该队列时,未完成的任务的总数就会增加。当使用者线程调用 task_done() 以表示检索了该项目、并完成了所有的工作时,那么未完成的任务的总数就会减少。当未完成的任务的总数减少到零时,join() 就会结束阻塞状态。

每个线程运行的时候就从队列里get一个url,这时候队列的长度就缩小1,然后完成的时候发送通知。直到队列为空的时候表示全部执行完毕。

调试的时候发现即使不要task_done()也可以得到一样的结果。但是主线程会一直阻塞着无法继续执行,所以task_done的任务是告诉主线程的当前任务完成了,并递减未完成的任务数,这样主线程才知道什么时候所有的任务都完成了,好继续执行。

使用线程池

可以自己实现一个线程池模块,也可以用已经存在的第三方线程池库,本文用的是后者,比较简单。

首先安装一个threadpool的库

pip install threadpool

然后用下面的代码完成和使用Queue一样的功能

import urllib2import osimport threadpooldef download(url):    urlHandle = urllib2.urlopen(url)    with open(os.path.basename(url)+".html","wb")as fp:        while 1:            contents=urlHandle.read(1024)            if not contents:                break            else:                fp.write(contents)def main():    ulrs = ["http://wiki.python.org/moin/Webprograming",    "https://www.baidu.com",    "http://wiki.python.org/moin/Documendation"]    thread_num=5    pool = threadpool.ThreadPool(thread_num)    requests = threadpool.makeRequests(download,ulrs)    print "put all request to thread pool"    for each in requests:        pool.putRequest(each)    pool.poll()  # 处理任务队列中新的请求    pool.wait()  # 阻塞用于等待所有执行结果    print "destroy all threads"    pool.dismissWorkers(thread_num,do_join=True)if __name__ == '__main__':    main()

 

转载于:https://www.cnblogs.com/streakingBird/p/4046102.html

你可能感兴趣的文章
kafka集群搭建与apiclient创建
查看>>
android如何添加桌面图标和卸载程序后自动删除图标
查看>>
【Android】12.1 Intent基本概念
查看>>
【云计算】qcow2虚拟磁盘映像转化为vmdk
查看>>
10、Cocos2dx 3.0游戏开发找小三之容器篇:Vector、Map、Value
查看>>
ExtJs之进度条实现
查看>>
C#实现把指定文件夹下的所有文件复制到指定路径下以及修改指定文件的后缀名...
查看>>
django之创建第4-3个项目-访问list数据
查看>>
黄聪:WordPress: 使用 wp_insert_attachment 上传附件
查看>>
旧手机作为USB无线网卡使用(分享WIFI、蓝牙连接)
查看>>
使用XML序列化器生成XML文件和利用pull解析XML文件
查看>>
git 本地提交后如果让服务器上的GIT 自动更新拉取
查看>>
我所了解的WEB开发(2) - PS切片
查看>>
UML学习小结
查看>>
结合Jexus + Kestrel 部署 asp.net core 生产环境
查看>>
shutdown命令用法
查看>>
Android TextView中文字通过SpannableString来设置超链接、颜色、字体等属性
查看>>
vim快速指南
查看>>
Strlcpy和strlcat——一致的、安全的字符串拷贝和串接函数【转】
查看>>
同态加密-Homomorphic encryption
查看>>