并发-2
并发编程
目录
- 创建进程的多种方式
 - join方法
 - 进程间数据默认隔离
 - 进程间通信(IPC机制)
 - 生产者消费者模型
 - 进程的相关方法
 - 守护进程
 - 僵尸进程和孤儿进程
 
创建进程的多种方式
- 
创建进程的方法
- 双击点击桌面程序图标
 - 用代码创建进程
 
 - 
如何用代码创建进程
- 
用process方法创建
from multiprocessing import Process import time def task(name): print(f'{name}正在运行') time.sleep(3) print(f'{name}运行结束') if __name__ == '__main__': p = Process(target=task, args=('jason',)) # 创建一个进程对象 p.start() # 告诉操作系统创建一个进程(异步操作) # task('jason') # 普通的函数调用是同步操作 print('主进程')创建进程的代码在不同的操作系统中 底层原理有区别!!!
在windows中 创建进程类似于导入模块
if __ name__ == '__ main__': 启动脚本
在mac、linux中 创建进程类似于直接拷贝
不需要启动脚本 但是为了兼容性 也可以使用 - 
用类来创建
class MyProcess(Process): def __init__(self, name): super().__init__() self.name = name def run(self): print(f'{self.name}正在运行') time.sleep(5) print(f'{self.name}运行结束') if __name__ == '__main__': obj = MyProcess('jason') obj.start() print('主进程') 
 - 
 
join方法
主程序等待子程序运行结束之后再运行
def task(name, n):
    print(f'{name}正在运行')
    time.sleep(n)
    print(f'{name}运行结束')
if __name__ == '__main__':
    p1 = Process(target=task, args=('jason', 1))  # args就是通过元组的形式给函数传参
    p2 = Process(target=task, args=('kevin', 2))  # 也可以通过kwargs={'name':'jason', 'n':1} 麻烦
    p3 = Process(target=task, args=('jerry', 3))
    start_time = time.time()
    
    
    p1.start()
    p1.join()
    p2.start()
    p2.join()
    p3.start()
    p3.join()
     end_time = time.time() - start_time
    print('总耗时:%s' % end_time)
 """ 总耗时为6.n s 原因: 类似于单进程 先运行完一个再运行下一个"""
    
    
    p1.start()
    p2.start()
    p3.start()
    p1.join()
    p2.join()
    p3.join()
    end_time = time.time() - start_time
    print('总耗时:%s' % end_time)
    print('主进程')
'''
并发进行,几乎同时进行
一定要看准join的执行位置 以及多任务情况下等待的目标
'''
进程间数据默认隔离
 多个进程之间的数据是默认相互隔离的
 如果真的想交互 需要借助于'管道'或者'队列'
from multiprocessing import Process
money = 100
def task():
    global money
    money = 666
    print('子进程打印的money', money)
if __name__ == '__main__':
    p = Process(target=task)
    p.start()
    p.join()
    print('父进程打印的money', money)
进程间通信(IPC机制)—— 队列
- 
什么是队列
 队列(先进先出)
 创建共享的进程队列,Queue是多进程安全的队列,用Queue方法实现多进程之间的数据传输
 - 
如何进行通信
from multiprocessing import Queue # 1.创建队列对象 q = Queue(3) # 括号内指定队列可以容纳的数据个数 默认:2147483647 # 2.往队列添加数据 # q.put(111) # print(q.full()) # 判断队列是否已经存满 # q.put(222) # q.put(333) # print(q.full()) # q.put(444) # 超出数据存放极限 那么程序一致处于阻塞态 直到队列中有数据被取出 # 3.从队列中取数据 print(q.get_nowait()) print(q.get_nowait()) print(q.get_nowait()) # 队列中如果没有数据可取 直接报错 # print(q.get()) # print(q.empty()) # 判断队列是否已经空了 # print(q.get()) # print(q.get()) # print(q.empty()) # print(q.get()) # 超出数据获取极限 那么程序一致处于阻塞态 直到队列中有数据被添加
方法 作用 不足 full() 判断队列是否已经存满 多进程下不能准确使用 empty() 判断队列是否已经空了 多进程下不能准确使用 get_nowait() 队列中如果没有数据可取 直接报错 多进程下不能准确使用 get() 取出队列中的数据 超出数据获取极限 那么程序一致处于阻塞态 
直到队列中有数据被添加put() 往队列添加数据 超出数据存放极限 那么程序一致处于阻塞态 
直到队列中有数据被取出 full()、empty()、get_nowait() 这些方法在单进程下可以实现,但在多进程下,由于这个队列是通用的,在同一时间一个进程存取,另一个进程进行取存,无法得到及时更新队列,所以并不能准确使用
 - 
IPC机制
- 主进程与子进程通信
 - 子进程与子进程通信
 
from multiprocessing import Queue, Process def procedure(q): q.put('子进程procedure往队里中添加了数据') def consumer(q): print('子进程的consumer从队列中获取数据', q.get()) if __name__ == '__main__': q = Queue() # 在主进程中产生q对象 确保所有的子进程使用的是相同的q p1 = Process(target=procedure, args=(q,)) p2 = Process(target=consumer, args=(q,)) p1.start() p2.start() print('主进程') - 
生产者消费者模型
分类 作用 举例 生产者 产生数据 获取网页数据的代码 消费队列/数据库 将产生的数据经行存储 将获取到的网页的数据存储到文本文件或数据库 消费者 处理存储的数据 从获取的网页数据中筛选出符合条件的数据 
 
进程的相关方法
| 执行操作 | 方法 | 
|---|---|
| 查看进程号 | current_process().pid os.getpid()/os.getppid()  | 
| 销毁子进程 | terminate() | 
| 判断进程是否存活 | is_alive() | 
- 
查看进程号
from multiprocessing import current_process import os current_process().pid os.getpid() os.getppid() - 
守护进程
- 
什么是守护进程
 伴随着守护对象的存活而存活 死亡而死亡
 - 
具体体现
from multiprocessing import Process import time def task(name): print('大内总管:%s存活' % name) time.sleep(3) print('大内总管:%s嗝屁' % name) if __name__ == '__main__': p = Process(target=task, args=('基佬',)) # p.daemon = True # 将子进程设置为守护进程:主进程代码结束 子进程立刻结束 p.start() p.daemon = True # 必须在start之前执行 print('天子Jason寿终正寝!!!') 
 - 
 - 
僵尸进程与孤儿进程
- 
僵尸进程
 进程已经运行结束 但是相关的资源并没有完全清空
 需要父进程参与回收
 - 
孤儿进程
 父进程意外死亡 子进程正常运行 该子进程就称之为孤儿进程
 孤儿进程也不是没有人管 操作系统会自动分配福利院接收
 
 - 
 

                
            
        
浙公网安备 33010602011771号