线程与进程
1 定义:
并发:任务数大于核心数,通过操作系统调度算法实现多个任务“一起执行”
实际是通过快速1切换任务,看上去是一起执行
并行:任务数小于核心数,任务是真正一起执行的
2 程序:不运行的软件是程序
进程:运行起来的应用程序就是进程
程序只有一个,但是进程可以有多个
3 创建进程
from multiprocessing import Process
p = Process(target = func,args=(num,),kwargs={})
p.start() # 执行子进程
p.join() 等待子进程执行结束
4 进程pid
当前进程os.getpid(),父进程 os.getppid()
5 进程之间的通信
1 创建queue队列对象
q=multiprocessing.Queue(3) # 3表示只能存放3个数据
参数:maxsize是队列中允许的最大项数。如果省略此参数,则无大小限制。返回值q是队列对象
2. put()方法,向队列中存放数据。如果队列已满,此方法将阻塞至有空间可用为止
3. get()返回q中的一个项目。如果q为空,此方法将阻塞,直到队列中有项目可用为止
4. get_nowait():不等待,直接抛出异常
5. full()如果q已满,返回为True
6. q.empty()如果调用此方法时q为空,返回为True
7. q.size()获取队列中数据的个数
6.进程池
使用multiprocessing模块中的Pool类,也就是进程池
from multiprocessing import Pool
pool = Pool(3)
pool.apply_async(func(i,),callback=alert)
# apply_async以非阻塞的形式创建进程 # apply阻塞
callback回调函数 将func的返回值传给alert
7.进程池中进程之间的通信,
使用from multiprocessing import Manager中的Queue
而不是multiprocessing中的Queue
q = Manager().Queue()
8.一个程序运行起来至少有一个进程,一个进程至少有一个线程
线程是cpu调度的最小单位,进程是操作系统分配的资源单位
进程比线程耗资源
线程可以共享进程中的资源
9. 创建线程 threading模块
join();当前线程执行完之后其他线程才会继续执行
进程
# 先下载歌曲,再听歌 import time def down_load(): for i in range(1,5): print("正在下载歌曲") time.sleep(0.5) def listen(): for i in range(1,5): print("正在听歌") time.sleep(1) start = time.time() down_load() listen() end = time.time() total_time = end -start # print('总共花了%ss'%total_time) # 总共花了6.037492513656616s
import time from multiprocessing import Process def down_load(): for i in range(1,5): print("正在下载歌曲") time.sleep(0.5) def listen(): for i in range(1,5): print("正在听歌") time.sleep(1) def main(): p1 = Process(target=down_load) #创建子进程 p2 = Process(target=listen) start = time.time() p1.start() #开启子进程 p2.start() p1.join() #等待子进程执行结束 p2.join() end = time.time() total_time = end -start print('总共花了%ss'%total_time) if __name__ == '__main__': main() # 总共花了4.157751083374023s
# 进程pid 当前进程 os.getpid(),父进程os.getppid() from multiprocessing import Process import os import time def func(): while True: time.sleep(1) print('---func---子进程为{},父进程为{}'.format(os.getpid(),os.getppid())) if __name__ == '__main__': print("---main--主进程为{},主进程的父进程{}".format(os.getpid(),os.getppid())) p1 = Process(target=func) p1.start()
# 给子进程传递响应的参数 args = (),kwargs={} import os from multiprocessing import Process def func(name,age,**kwargs): print("--func--子进程为name=%s,pid=%d"%(name,os.getpid())) print(age) print(kwargs) if __name__ == '__main__': p1 = Process(target=func,args=('johnson',22),kwargs={'weight':123}) p1.start() # --func--子进程为name=johnson,pid=10708 # 22 # {'weight': 123}
# 进程间不共享全局变量 import multiprocessing list = [1,2,3] def func1(): for i in range(1,5): list.append(i) print('func1:',list) def func2(): print('func2:',list) if __name__ == '__main__': process1 = multiprocessing.Process(target=func1) process2 = multiprocessing.Process(target=func2) process1.start() process2.start() print('外层:',list) # 外层: [1, 2, 3] # func1: [1, 2, 3, 1, 2, 3, 4] # func2: [1, 2, 3]
queue相关用法
from multiprocessing import Queue q = Queue(3) # 创建对象,最多放三条数据 print(q.empty()) q.put("johnson") print(q.empty()) q.put("mary") q.put("way") print(q.full()) # print(q.get()) # print(q.get()) # print(q.get()) # print(q.get()) # print(q.get_nowait()) print(q.qsize())
from multiprocessing import Queue import multiprocessing import time def down_load(q): data = ['a','b','c'] for i in data: time.sleep(0.5) q.put(i) print("下载完了数据") def work(q): for i in range(q.qsize()): print(q.get()) print("处理完了数据") if __name__ == '__main__': q = Queue() p1 = multiprocessing.Process(target=down_load,args=(q,)) p2 = multiprocessing.Process(target=work,args=(q,)) p1.start() p2.start()
from multiprocessing import Queue import multiprocessing import time def down_load(q): data = ['a','b','c'] for i in data: time.sleep(0.5) q.put(i) print("下载完了数据") def work(q): while True: print(q.get()) print('处理完了数据') if __name__ == '__main__': q = Queue() p1 = multiprocessing.Process(target=down_load,args=(q,)) p2 = multiprocessing.Process(target=work,args=(q,)) p1.start() p2.start() # a # b # 下载完了数据 # c
Pool相关用法
from multiprocessing import Pool def down_load(movie_name): for i in range(5): print("电影{},下载进度{}%".format(movie_name,i/4*100)) time.sleep(1) return movie_name+'--->' def alert(movie_name): print("恭喜{}下载完成了。。。。".format(movie_name)) if __name__ == '__main__': movie_lst = ['西红柿首富', '功夫小子', '功夫熊猫', '叶问', '功 夫', '战狼', '红海行动'] pool = Pool(4) for movie_name in movie_lst: pool.apply_async(down_load,(movie_name,),callback=alert) # 以非阻塞的形式创建进程 pool.close() pool.join() # 电影西红柿首富,下载进度0.0% # 电影功夫小子,下载进度0.0% # 电影功夫熊猫,下载进度0.0% # 电影叶问,下载进度0.0% # 电影西红柿首富,下载进度25.0% # 电影功夫小子,下载进度25.0% # 电影功夫熊猫,下载进度25.0% # 电影叶问,下载进度25.0% # 电影西红柿首富,下载进度50.0% # 电影功夫小子,下载进度50.0% # 电影功夫熊猫,下载进度50.0% # 电影叶问,下载进度50.0% # 电影西红柿首富,下载进度75.0% # 电影功夫小子,下载进度75.0% # 电影功夫熊猫,下载进度75.0% # 电影叶问,下载进度75.0% # 电影西红柿首富,下载进度100.0% # 电影功夫小子,下载进度100.0% # 电影功夫熊猫,下载进度100.0% # 电影叶问,下载进度100.0% # 电影功 夫,下载进度0.0% # 恭喜西红柿首富--->下载完成了。。。。 # 电影战狼,下载进度0.0% # 恭喜功夫小子--->下载完成了。。。。 # 恭喜功夫熊猫--->下载完成了。。。。 # 电影红海行动,下载进度0.0% # 恭喜叶问--->下载完成了。。。。 # 电影功 夫,下载进度25.0% # 电影战狼,下载进度25.0% # 电影红海行动,下载进度25.0% # 电影功 夫,下载进度50.0% # 电影战狼,下载进度50.0% # 电影红海行动,下载进度50.0% # 电影功 夫,下载进度75.0% # 电影战狼,下载进度75.0% # 电影红海行动,下载进度75.0% # 电影功 夫,下载进度100.0% # 电影战狼,下载进度100.0% # 电影红海行动,下载进度100.0% # 恭喜功 夫--->下载完成了。。。。 # 恭喜战狼--->下载完成了。。。。 # 恭喜红海行动--->下载完成了。。。。
# 验证上面始终只有三个进程号 from multiprocessing import Pool import os,time,random def func(i): start = time.time() print('%d开始执行,子进程号是%d,父进程号%d'%(i,os.getpid(),os.getppid())) time.sleep(random.random()*2) end = time.time() print("%d执行完毕,耗时%.2f"%(i,end-start)) if __name__ =="__main__": pool = Pool(3) print("主进程号:",os.getpid()) for i in range(10): pool.apply_async(func,(i,)) pool.close() pool.join() print('-------end------') # 主进程号: 5800 # 0开始执行,子进程号是15944,父进程号5800 # 1开始执行,子进程号是8916,父进程号5800 # 2开始执行,子进程号是16348,父进程号5800 # 2执行完毕,耗时1.17 # 3开始执行,子进程号是16348,父进程号5800 # 3执行完毕,耗时0.14 # 4开始执行,子进程号是16348,父进程号5800 # 0执行完毕,耗时1.50 # 5开始执行,子进程号是15944,父进程号5800 # 1执行完毕,耗时1.60 # 6开始执行,子进程号是8916,父进程号5800 # 4执行完毕,耗时0.29 # 7开始执行,子进程号是16348,父进程号5800 # 6执行完毕,耗时1.01 # 8开始执行,子进程号是8916,父进程号5800 # 7执行完毕,耗时1.40 # 9开始执行,子进程号是16348,父进程号5800 # 5执行完毕,耗时1.78 # 8执行完毕,耗时1.99 # 9执行完毕,耗时1.81 # -------end------
进程间通信
import os from multiprocessing import Manager from multiprocessing import Pool import time def write(q): print('write子进程%d启动,父进程%d'%(os.getpid(),os.getppid())) for i in "python1234": time.sleep(0.5) q.put(i) def reader(q): print("reader子进程%d启动,父进程%d"%(os.getpid(),os.getppid())) time.sleep(1) for i in range(q.qsize()): time.sleep(0.5) print(q.get()) if __name__ == '__main__': print("主进程执行%d"%os.getpid()) q = Manager().Queue() pool = Pool(3) pool.apply_async(write,(q,)) time.sleep(1) pool.apply_async(reader,(q,)) pool.close() pool.join() # 主进程执行3140 # write子进程9264启动,父进程3140 # reader子进程10608启动,父进程3140 # p # y # t
线程
from threading import Thread import time def down_load(): for i in range(1,5): print("正在下载歌曲") time.sleep(0.5) def listen(): for i in range(1,5): print("正在听歌") time.sleep(1) t1 = Thread(target=down_load) t2 = Thread(target=listen) start = time.time() t1.start() t2.start() t1.join() t2.join() end = time.time() print("耗时:",end-start,"s") # 正在下载歌曲 # 正在听歌 # 正在下载歌曲 # 正在听歌 # 正在下载歌曲 # 正在下载歌曲 # 正在听歌 # 正在听歌 # 耗时: 4.002870082855225 s
from threading import Thread import time list = [11,22] def func1(): list.append(33) def func2(): time.sleep(1) print('--func2--',list) t1 = Thread(target=func1) t2 = Thread(target=func2) t1.start() t2.start() print("main--:",list) # main--: [11, 22, 33] # --func2-- [11, 22, 33]