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()

  

  

  

原文地址:https://www.cnblogs.com/alasijia/p/8523529.html