一、多任务
定义: 多任务就是同一时刻多个任务同时执行。
实现多任务的原理: CPU在多个应用程序之间的高速切换。
二、进程
定义: 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
程序和进程
- 程序: 编写完毕的代码,在没有运行的时候,称之为程序。
- ** 进程:** 正在运行着的代码,就成为进程。
- 对应关系: 程序只有一个,进程可以有多个
进程的创建:
新创建的进程在内存独立开辟一块空间,不与其他进程共享空间、数据。
同一个进程中,新创建的线程与此进程里其他线程共享空间、数据。
多进程
实例:一定要把开进程的代码写在if name==‘main’:下面
from multiprocessing import Process
import time
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) # target表示调用对象,即子进程要执行的任务
t1.start()
t2.start()
多进程同时进行
from multiprocessing import Process
count=0
def hanshu1():
global count
for i in range(1000):
count+=1
print("函数1:",count)
def hanshu2():
global count
for i in range(1000):
count+=1
print("函数2:",count)
if __name__=="__main__": # 写多线程,进程必须要写的
t1=Process(target=hanshu1)
t2=Process(target=hanshu2)
t1.start()
t2.start()
注意:
- 需要使用关键字的方式来指定参数
- args指定的为传给target函数的位置参数,是一个元组形式,必须有逗号
进程里的一些方法:
-
p.start():启动进程,并调用该子进程中的p.run()
-
p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法
-
p.join([timeout]):主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。timeout是可选的超时时间,
需要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程 -
getppid()父进程id
-
getpid() #当前进程id
进程的状态:
就绪:分配到除CPU以外的所有必要资源,只要获得处理机便可以立即执行
阻塞:状态正在执行的进程,由于等待某个事件发生而无法执行时,便放弃处理机而处于阻塞状态
执行:状态当进程已获得处理机,其程序正在处理机上执行
队列 (先进先出的存储数据结构)
实现进程之间的通讯
两个进程通讯:就是一个子进程往queue中写内容,另一个进程从queue中取出数据
队列实例:
from multiprocessing import Queue
q=Queue(4)
q.put("包子")
q.put("香蕉")
q.put("西瓜")
print("执行到这了")
q.put("猪肘子")
print("开始吃")
print(q.get()) # 先进先出
print(q.get())
print(q.get())
print(q.get())
from multiprocessing import Queue
q=Queue(4)
q.put("包子")
q.put("香蕉")
q.put("西瓜")
print(q.qsize())
while q.qsize()>0: # 与上面代码功能相同
print(q.get())
队列满和空时阻塞
from multiprocessing import Queue
q=Queue(3)
q.put(10)
q.put(20)
q.put(30)
try:
q.put(40,block=False) # block堵塞,block=False,不想等直接结束,报异常
except:
print("队满了,没法再装了")
print("到这了")
from multiprocessing import Queue
q=Queue(3)
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 produce(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(1)
p1=Process(target=produce,args=(q,))
p2=Process(target=consumer,args=(q,))
p1.start()
p2.start()
# in __init__
# self._args = tuple(args)
进程的子类化
from multiprocessing import Process
import os,time
class SubProcess(Process):
def __init__(self,x):
super().__init__()
self.x=x
def run(self): # 重新编写run函数,覆盖父类的run方法。进程启动的时候调用此方法
for i in range(self.x):
print("启动进程",i,os.getpid())
time.sleep(1)
if __name__=="__main__":
p=SubProcess(3)
p.start()
p1 = SubProcess(3)
p1.start()
# 启动进程 0 8340
# 启动进程 0 6872
# 启动进程 1 8340
# 启动进程 1 6872
# 启动进程 2 8340
# 启动进程 2 6872
用子类化实现生产和消费包子
from multiprocessing import Process,Queue
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): # 必须写run
for i in range(10):
bz=self.q.get()
print("消费"+bz)
if __name__=='__main__':
q = Queue(1)
p1=Producer(q)
p2=Consumer(q)
p1.start()
p2.start()
进程池Pool
作用: 达到进程重复利用
join 主进程等待所有子进程执行完毕,必须在close之后
close 等待所有进程结束才关闭线程池
from multiprocessing import Pool
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="abcde"
for x in a:
p.apply(hanshu1,(x,)) # 阻塞,同时只跑一个进程
p.close()
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 = "abcde"
for x in a:
p.apply_async(hanshu1,(x,)) # 不阻塞,同时可以跑多个进程
p.close()
p.join() # 阻塞主进程,等待子进程结束
练习进程池
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()
# 张三 我在写代码
# 去抽烟因为张三写完代码了
下载器工作原理
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()
线程
import time
from threading import Thread
count=0
def hanshu1():
global count
for i in range(10):
count+=1
print("函数1",count)
def hanshu2():
global count
for i in range(10):
count+=1
print("函数2",count) # 线程共用进程里的所有资源,t1,执行完结果为10,因为共用资源,所有函数2 count为20
if __name__ == '__main__':
t1=Thread(target=hanshu1)
t2=Thread(target=hanshu2)
t1.start()
t1.join()
t2.start()
t2.join()
# 函数1 10
# 函数2 20
多线程
import time
from threading import Thread
def sing():
for i in range(10):
print("唱歌%d"%(i+1))
time.sleep(1)
def dance():
for i in range(10):
print("跳舞%d"%(i+1))
time.sleep(1)
if __name__ == '__main__': # 在一个进程里,线程
t1=Thread(target=sing)
t2=Thread(target=dance)
t1.start()
t2.start()
线程的传参
import time
from threading import Thread
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("主线程结束了")
# 0
# 主线程结束了
# 1
# 2
# 3
# 4
join()方法
import time
from threading import Thread
def sing():
for i in range(10):
print("唱歌%d"%(i+1))
time.sleep(1)
def dance():
for i in range(10):
print("跳舞%d"%(i+1))
time.sleep(1.5)
if __name__ == '__main__': # 在一个进程里,线程
t1=Thread(target=sing)
t2=Thread(target=dance)
t1.start()
# t1.join()
t2.start()
t1.join()
t2.join()
print("结束")
线程的方法
import time,threading
from threading import Thread
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.5)
if __name__ == '__main__': # 在一个进程里,线程
t1=Thread(target=sing,name="刘德华")
t2=Thread(target=dance,name="张惠妹")
t1.start()
# t1.join()
t2.start()
print(threading.enumerate()) # 跳舞1[<_MainThread(MainThread, started 1544)>, <Thread(刘德华, started 4608)>, <Thread(张惠妹, started 9900)>]
print(threading.active_count(),len(threading.enumerate()))
t1.join()
t2.join()
print("结束")
线程子类化
import time,threading
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 C(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="张三"
t1=T(t)
# t1 = T("张三")
t2=C(t)
t1.start()
t2.start()
共享全局变量
import threading
g_num=0
def hanshu1():
global g_num
g_num+=5
def hanshu2():
print(g_num) # 5
if __name__ == '__main__':
t1=threading.Thread(target=hanshu1)
t2=threading.Thread(target=hanshu2)
t1.start()
t2.start()
会达不到预期效果
import threading
g_num=0
def hs1():
global g_num
for i in range(100000):
g_num+=1
print("函数1",g_num)
def hs2():
global g_num
for i in range(100000):
g_num += 1
print("函数2",g_num)
if __name__ == '__main__':
t1=threading.Thread(target=hs1)
t2=threading.Thread(target=hs2)
t1.start() # 会达不到预期效果
t2.start()