多任务:对于电脑来说多任务就是同时运行多个应用程序。
在python中实现多进程有三种方式,进程、线程、协程。
进程
进程:运行起来的应用程序就称之为进程。
程序和进程的对应关系:程序只有一个,但是进程可以有多个。
进程是系统进行资源分配和调度的基本单位。
创建多进程
#使用进程让唱歌和跳舞一起执行
import time
from multiprocessing import Process
def sing():
for i in range(10):
print("我在唱第{}句歌词".format(i+1))
time.sleep(1)
def dance():
for i in range(10):
print("我在跳第{}句舞蹈".format(i+1))
time.sleep(1)
if __name__=="__main__":
t1=Process(target=sing)
t2=Process(target=dance)
t1.start()#用来启动进程并执行任务
t2.start()
#不使用多进程实现先唱后跳
# sing()
# dance()
进程和全局变量
from multiprocessing import Process
# count=0
# def hanshu1():
# for i in range(1000):
# count+=1
# #count=count+1 #局部变量和全局变量冲突
#每个进程访问变量互补影响
count=0
def hanshu1():
global count
for i in range(1000):
count=count+1
print('函数1:',count)
def hanshu2():
global count
for i in range(1000):
count=count+1
print('函数2:',count)
if __name__=="__main__":
t1=Process(target=hanshu1)
t2=Process(target=hanshu2)
t1.start()#1000
t2.start()#1000
# hanshu1()#1000
# hanshu2()#2000
传递参数和进程号
from multiprocessing import Process
import os
def sing(num):
print("参数是",num,'进程的ID',os.getpid(),'父进程',os.getppid())
def dance(num):
print("参数是",num,'进程的ID',os.getpid(),'父进程',os.getppid())
if __name__=='__main__':
print('主进程ID',os.getpid())
p1=Process(target=sing,args=(9,))# self._args = tuple(args)
p2=Process(target=dance,args=(99,))
p1.start()
p2.start()
'''
主进程ID 5024
参数是 99 进程的ID 12236 父进程 5024
参数是 9 进程的ID 12244 父进程 5024
'''
进程的状态
就绪状态,就绪、执行状态,阻塞状态
进程之间通信
可以使用队列,队列:先进先出的存储结构。
两个进程通讯,就是一个子进程往队列中写,另一个取。
from multiprocessing import Queue
q=Queue(4)#表示只能存放4个数据,队列对象返回值q是
q.put('包子')
q.put('香蕉')
q.put('西瓜')
print('执行到这了')
q.put('馒头')
print('开始吃')
#队列中有多少数据
print(q.qsize())
#判断队列中是否放满了
print(q.full())
while q.qsize()>0:
print(q.get())#获取数据
print(q.empty())#判断队列是否为空
'''
执行到这了
开始吃
4
True
包子
香蕉
西瓜
馒头
True
'''
put() get()方法
from multiprocessing import Queue
q=Queue(3)#表示只能存放3个数据,队列对象返回值q是
q.put(10)
q.put(20)
q.put(30)
#1
try:
q.put(40,block=False)#阻塞
except:
print("队满了,没法再装了")
print('到这了')
#2
from multiprocessing import Queue
q=Queue(3)#表示只能存放3个数据,队列对象返回值q是
q.put(10)
q.put(20)
print(q.get())
print(q.get())
try:
print(q.get(block=False))
except:
print("没人放东西了")
print('程序走到这了')
'''
队满了,没法再装了
到这了
10
20
没人放东西了
程序走到这了
'''
生产者和消费者
from multiprocessing import Queue, Process
import time
#生产者和消费者
def producer(q):
#往队列中写入数据
for i in range(10):
bz = '包子%d' % (i + 1)
print("生产" + bz)
q.put(bz)
time.sleep(1)
def consumer(q):
#读取队列中的数据
for i in range(10):
bz = q.get()
print('消费' + bz)
if __name__ == '__main__':
q = Queue(3)
p1 = Process(target=producer, args=(q,))
p2 = Process(target=consumer, args=(q,))
p1.start()
p2.start()
进程子类化
#进程子类化
from multiprocessing import Process
import os,time
class SubProcess(Process):#进程子类化
def __init__(self,x):
super().__init__()
self.x=x
def run(self):
for i in range(self.x):
print("启动进程",os.getpid())
time.sleep(1)
if __name__=='__main__':
p=SubProcess(3)#
p.start()
p1=SubProcess(3)
p1.start()
生产者和消费者子类化
from multiprocessing import Queue,Process
import time
class Producer(Process):
def __init__(self,q):
super().__init__()
self.q = q
def run(self):
for i in range(10):
bz='包子%d'%(i+1)
print("生产",bz)
self.q.put(bz)
time.sleep(1)
class Consumer(Process):
def __init__(self, q):
super().__init__()
self.q = q
def run(self):
for i in range(10):
bz=self.q.get()
print('吃',bz)
if __name__=='__main__':
q=Queue(5)
p1=Producer(q)
p2=Consumer(q)
p1.start()
p2.start()
进程池
#进程池:p.apply(hanshu1,(x,))#阻塞,同时跑一个进程
from multiprocessing import Pool
import time
def hanshu1(name):
for i in range(5):
print(name,i)
time.sleep(1)
if __name__=='__main__':
p=Pool(5)#同时跑的进程数
a='abcdefghijk'
for x in a:
p.apply(hanshu1,(x,))#阻塞,同时跑一个进程
p.close()#阻塞主进程,等待子进程结束
'''
a 0
a 1
a 2
a 3
a 4
b 0
b 1
b 2
b 3
b 4
c 0
'''
#进程池:apply_async是异步非阻塞式的。
from multiprocessing import Pool
import time
def hanshu1(name):
for i in range(5):
print(name,i)
time.sleep(1)
if __name__=='__main__':
p=Pool(5)#同时跑的进程数
a='abcdefghijk'
for x in a:
p.apply_async(hanshu1,(x,))#apply_async是异步非阻塞式的。
p.close()#阻塞主进程,等待子进程结束
p.join()
"""
a 0
b 0
c 0
d 0
e 0
a 1
b 1
c 1
d 1
e 1
a 2
b 2
c 2
d 2
e 2
a 3
b 3
c 3
"""
from multiprocessing import Pool
import time
def zuoye(name):
print(name,"我在写代码")
time.sleep(1)
return name+"写完代码了"
def chouyan(status):
print("去抽烟因为"+status)
if __name__=="__main__":
p=Pool(1)
p.apply_async(zuoye,("张三",),callback=chouyan)
p.close()#等待所有进程结束才关闭进程池
p.join()#join 主进程等待所有子进程执行完毕,必须在close之后
'''
张三 我在写代码
去抽烟因为张三写完代码了
'''
例子:迅雷下载器
#例子:迅雷下载器
from multiprocessing import Pool
import time
def downLoad(movie):
for i in range(5):
print(movie,"下载进度%.2f%%"%((i+1)/5*100))
time.sleep(1)
return movie
def alert(name):
print(name,"下载完毕,请收看")
if __name__=="__main__":
movies=['哪吒',"金刚葫芦娃","黑猫警长",'小青龙','亚洲飞鹰','A计划']
p=Pool(3)
for movie in movies:
p.apply_async(downLoad,args=(movie,),callback=alert)
p.close()
p.join()
线程
进程是资源分配的最小单位,线程是CPU调度的最小单位(程序真正调用的是线程),每一个进程至少有一个线程。
#他两是是一个进程
from threading import Thread
import time
import os
def sing():
for i in range(10):
print("唱儿歌%d"%(i+1),os.getpid())
time.sleep(1)
def dance():
for i in range(10):
print("跳舞%d"%(i+1),os.getpid())
time.sleep(1)
if __name__ == '__main__':
t1=Thread(target=sing)
t2=Thread(target=dance)
t1.start()
t2.start()
守护线程
from threading import Thread
import time
def get(num):
for i in range(num):
print(i)
time.sleep(1)
if __name__ == '__main__':
t1=Thread(target=get,args=(5,))
#注意:需要在线程开启的时候设置成守护线程
t1.setDaemon(True)#守护线程,主线程结束,守护线程也就结束,不管是否执行完毕
t1.start()
print('主线程结束了')
join()
from threading import Thread
import time
import os
def sing():
for i in range(10):
print("唱儿歌%d"%(i+1),os.getpid())
time.sleep(1)
def dance():
for i in range(10):
print("跳舞%d"%(i+1),os.getpid())
time.sleep(1)
if __name__ == '__main__':
t1=Thread(target=sing)
t2=Thread(target=dance)
t1.start()
# t1.join()#在t2前加载,t1执行完后,t2和主线程才执行这里join会阻塞t2,在执行跳舞的时候,主线程先结束
t2.start()
# t1.join()#t1,t2,执行完成后主线程才执行,在这里会阻塞主进程,最后执行结束
t1.join()
t2.join()
print('结束')
threading.current_thread():返回当前的线程变量
threading.enumerate():返回一个正在运行线程的list
threading.active_count():代表enumerate()里存活的线程数量
#他两是是一个进程
from threading import Thread
import threading
import time
import os
def sing():
for i in range(10):
print("唱儿歌%d"%(i+1),threading.current_thread())
time.sleep(1)
def dance():
for i in range(10):
print("跳舞%d"%(i+1),threading.current_thread())
time.sleep(1)
if __name__ == '__main__':
t1=Thread(target=sing,name="刘德华")#给线程起了个名字
t2=Thread(target=dance,name='张惠妹')
t1.start()
t2.start()
print(threading.enumerate())#返回一个正在运行线程的list
print(threading.active_count(),len(threading.enumerate()))#代表enumerate()里存活的线程数量
t1.join()
t2.join()
print('结束')
线程子类化
#线程子类化
import threading,time
from threading import Thread
class T(Thread):
def __init__(self,name):
super().__init__()
self.name=name
def run(self):
for i in range(10):
print(self.name,"跳舞%d"%(i+1))
time.sleep(1)
if __name__ == '__main__':
t=T("张三")
t.start()
#线程子类化
import threading,time
from threading import Thread
class T(Thread):
def __init__(self,name):
super().__init__()
self.name=name
def run(self):
for i in range(10):
print(self.name,"跳舞%d"%(i+1))
time.sleep(1)
class T1(Thread):
def __init__(self,name):
super().__init__()
self.name=name
def run(self):
for i in range(10):
print(self.name,"唱歌%d"%(i+1))
time.sleep(1)
if __name__ == '__main__':
t=T("张三")
t.start()
y=T1("zhang")
y.start()
共享全局变量的问题
import threading
g_num=0
def hanshu1():
global g_num
g_num+=5
def hanshu2():
print(g_num)
if __name__ == '__main__':
t1=threading.Thread(target=hanshu1)
t2=threading.Thread(target=hanshu2)
t1.start()
t2.start()
#5
多线程开发的时候共享全局变量会带来资源竞争效果。也就是数据不安全
from threading import Thread
g_num=0
def hanshu1():
global g_num
for i in range(100000):
# time.sleep(1)
g_num+=1
print("函数1",g_num)
def hanshu2():
global g_num
for i in range(100000):
# time.sleep(1)
g_num+=1
print("函数2",g_num)
if __name__ == '__main__':
t1=Thread(target=hanshu1)
t2=Thread(target=hanshu2)
t1.start()
# t1.join()
t2.start()
'''
函数1 143776
函数2 192931
'''