gpt4 book ai didi

Python多线程原理与用法实例剖析

转载 作者:qq735679552 更新时间:2022-09-28 22:32:09 27 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章Python多线程原理与用法实例剖析由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

本文实例讲述了python多线程原理与用法。分享给大家供大家参考,具体如下:

先来看个栗子:

下面来看一下i/o秘籍型的线程,举个栗子——爬虫,下面是爬下来的图片用4个线程去写文件 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import re
import urllib
import threading
import queue
import timeit
def gethtml(url):
   html_page = urllib.urlopen(url).read()
   return html_page
# 提取网页中图片的url
def geturl(html):
   pattern = r 'src="(http://img.*?)"' # 正则表达式
   imgre = re. compile (pattern)
   imglist = re.findall(imgre, html) # re.findall(pattern,string) 在string中寻找所有匹配成功的字符串,以列表形式返回值
   return imglist
class getimg(threading.thread):
   def __init__( self , queue, thread_name = 0 ): # 线程公用一个队列
     threading.thread.__init__( self )
     self .queue = queue
     self .thread_name = thread_name
     self .start() # 启动线程
   # 使用队列实现进程间通信
   def run( self ):
     global count
     while (true):
       imgurl = self .queue.get() # 调用队列对象的get()方法从队头删除并返回一个项目
       urllib.urlretrieve(imgurl, 'e:\mnt\girls\%s.jpg' % count)
       count + = 1
       if self .queue.empty():
         break
       self .queue.task_done() # 当使用者线程调用 task_done() 以表示检索了该项目、并完成了所有的工作时,那么未完成的任务的总数就会减少。
imglist = []
def main():
   global imglist
   url = "http://huaban.com/favorite/beauty/" # 要爬的网页地址
   html = gethtml(url)
   imglist = geturl(html)
def main_1():
   global count
   threads = []
   count = 0
   queue = queue.queue()
   # 将所有任务加入队列
   for img in imglist:
     queue.put(img)
   # 多线程爬去图片
   for i in range ( 4 ):
     thread = getimg(queue, i)
     threads.append(thread)
   # 阻塞线程,直到线程执行完成
   for thread in threads:
     thread.join()
if __name__ = = '__main__' :
   main()
   t = timeit.timer(main_1)
   print t.timeit( 1 )

4个线程的执行耗时为:0.421320716723秒 。

修改一下main_1换成单线程的:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def main_1():
   global count
   threads = []
   count = 0
   queue = queue.queue()
   # 将所有任务加入队列
   for img in imglist:
     queue.put(img)
   # 多线程爬去图片
   for i in range ( 1 ):
     thread = getimg(queue, i)
     threads.append(thread)
   # 阻塞线程,直到线程执行完成
   for thread in threads:
     thread.join()

单线程的执行耗时为:1.35626623274秒 。

Python多线程原理与用法实例剖析

再来看一个:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import threading
import timeit
def countdown(n):
   while n > 0 :
     n - = 1
def task1():
   count = 100000000
   thread1 = threading.thread(target = countdown, args = (count,))
   thread1.start()
   thread1.join()
def task2():
   count = 100000000
   thread1 = threading.thread(target = countdown, args = (count / / 2 ,))
   thread2 = threading.thread(target = countdown, args = (count / / 2 ,))
   thread1.start()
   thread2.start()
   thread1.join()
   thread2.join()
if __name__ = = '__main__' :
   t1 = timeit.timer(task1)
   print "countdown in one thread " , t1.timeit( 1 )
   t2 = timeit.timer(task2)
   print "countdown in two thread " , t2.timeit( 1 )

task1是单线程,task2是双线程,在我的4核的机器上的执行结果:

countdown in one thread  3.59939150155 。

countdown in two thread  9.87704289712 。

天呐,双线程比单线程计算慢了2倍多,这是为什么呢,因为countdown是cpu密集型任务(计算嘛) 。

Python多线程原理与用法实例剖析

i/o密集型任务:线程做i/o处理的时候会释放gil,其他线程获得gil,当该线程再做i/o操作时,又会释放gil,如此往复; 。

cpu密集型任务:在多核多线程比单核多线程更差,原因是单核多线程,每次释放gil,唤醒的哪个线程都能获取到gil锁,所以能够无缝执行(单核多线程的本质就是顺序执行),但多核,cpu0释放gil后,其他cpu上的线程都会进行竞争,但gil可能会马上又被cpu0(cpu0上可能不止一个线程)拿到,导致其他几个cpu上被唤醒后的线程会醒着等待到切换时间后又进入待调度状态,这样会造成线程颠簸(thrashing),导致效率更低.

希望本文所述对大家python程序设计有所帮助.

原文链接:https://www.cnblogs.com/onepiece-andy/p/python-thread-analyze.html 。

最后此篇关于Python多线程原理与用法实例剖析的文章就讲到这里了,如果你想了解更多关于Python多线程原理与用法实例剖析的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com