python进阶--多线程多进程
一、线程和进程
进程是拥有独立内存,能够独立运行的最小单位,也是程序执行的最小单位,线程是程序运行过程中,一个单一的顺序控制流程,是程序执行流的最小单位,一个进程至少包含一个线程,多线程共享进程的内存空间和上下文环境,线程上下文切换比进程上下文切换要快得多
二、python与多线程
python中多线程涉及模块-----threading模块
1. 多线程
import threading,time,requests
def downHtml(url,name):#下载网页
content=requests.get(url).content#返回的是二进制的内容
f=open(name+'.html','wb')#打开html文件
f.write(content)#将下载网页的内容写到文件中
f.close()#关闭文件
urls=[#url列表
['aaa','http://www.aaa.cn'],
['bbb','http://www.bbb.cn'],
['ccc','http://www.ccc.cn'],
]
start_time=time.time()#记录程序执行前时间
threads=[]
for url in urls:
#实例化线程类,接收连个参数,一个是函数名,第二个是函数需要的参数,args代表接收多个参数,用逗号隔开,如果是一个参数时,也要写逗号,否则会当字符串处理
t=threading.Thread(target=downHtml,args=(url[1],url[0]))
#启动线程活动
t.start()
threads.append(t)
#为什么时间统计完,程序还没有结束?因为线程是独立的,在运行py时,默认有个主线程, 主线程导入模块,读代码,执行代码-起了三个子线程后,主线程继续执行,执行完,就显示时长了,也就是这个时间只包括主线程的执行时间,不包含三个子线程执行程序的时间
#解决办法,让主程序等待子程序都执行完再统计时间
for t in threads:#循环等待3个子线程都执行完
t.join()#主线程等待子线程结束,
end_time = time.time()
print(end_time-start_time)
2.多线程处理返回结果
启动多线程调用有返回值的函数时,返回值是获取不到的,
解决办法,将返回值加到一个数组中
import threading
res=[]
def sum(x,y):
res.append(x+y)
for i in range(5):
t=threading.Thread(target=sum,args=(i,i))
t.start()
print(res)
#返回结果[0,2,4,6,8]
3.守护线程
设置线程为Daemon后,也就是设置线程为守护线程后,主线程运行完,不管守护线程有没有执行完,立马销毁,也就是主线程需要等非守护线程执行结束才能结束,不需要等守护线程。如果想和主线程一起销毁就设置为守护线程,如果想让主线程等待这个线程执行完后销毁,则不要设置为守护线程
import threading,time
def pz():
print(‘’)
time.sleep(2)
print('守护线程')
#threads=[]
for i in range(50):
t=threading.Thread(target=pz)
#设置子线程为守护线程,主线程一旦结束,子线程立马结束,不管子线程有没有执行完成
t.setDaemon(True)
t.start()
#threads.append(t)
#如果主线程等待子进程,设置的守护进程就无效了
#for i in threads:
# t.join()
print('done')
#因为守护进程要等待2s,主进程只是打印done很快,所以最后输出只有done,主进程不等守护进程执行结束
4.线程锁
多线程在同时修改同一个全局变量时,可能会造成数据错误,为了避免这种错误,可以使用线程锁,python3可以不加,程序会自动加锁
import threading
from threading import Lock
num = 0
lock = Lock() # 申请一把锁
def run():
global num
lock.acquire() # 加锁
num += 1
lock.release() # 解锁
lis = []
for i in range(5):
t = threading.Thread(target=run)
t.start()
lis.append(t)
for t in lis:
t.join()
print('over', num)
#返回结果:over 5
5.多进程
多线程不能利用多核cpu,多进程可以, 启动多进程使用multiprocessing模块
import multiprocessing,threading,time
def run2():
print('这是多线程启动的')
def run():
time.sleep(2)
print('多进程')
for i in range(5):#每个进程中启动5个线程
t=threading.Thread(target=run2)
t.start()
if __name__=='__main__':#启动进程必须放在这个里面
for i in range(5):
p=multiprocessing.Process(target=run)#启动5个进程
p.start()

浙公网安备 33010602011771号