一、线程和进程
进程是拥有独立内存,能够独立运行的最小单位,也是程序执行的最小单位,线程是程序运行过程中,一个单一的顺序控制流程,是程序执行流的最小单位,一个进程至少包含一个线程,多线程共享进程的内存空间和上下文环境,线程上下文切换比进程上下文切换要快得多
二、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()