zoukankan      html  css  js  c++  java
  • 05.进程

    01.进程

    1.1 什么是进程?

    1.进程是资源分配的最小单位( 内存、cpu、网络、io)
    2.一个运行起来的程序就是一个进程
      什么是程序(程序是我们存储在硬盘里的代码)
      硬盘(256G)、内存条(8G)
      当我们双击图标,打开程序的时候,实际上就是通过I/O操作(读写),硬盘中的代码读取到内存条里
      内存条就是我们所指的资源(程序分配了内存资源,就变成了进程)
     CPU分时
      CPU比你的手速快多了,分时处理每个线程,但是由于太快然你觉得每个线程都是独占cpu
      cpu是计算,只有时间片到了,获取cpu,线程真正执行
      当你想使用 网络、磁盘等资源的时候,需要cpu的调度
    3.进程具有独立的内存空间,所以没有办法相互通信

    1.2 进程如何通信?

    同一程序下进程通信
    1、进程queue(父子进程通信)
    2、pipe(同一程序下两个进程通信)
    3、managers(同一程序下多个进程通信)
    Java项目和python项目如何通信
    1、RabbitMQ、redis等(不同程序间通信)

    1.3 为什么需要进程池?

    一次性开启指定数量的进程
    如果有十个进程,有一百个任务,一次可以处理多少个(一次性只能处理十个)
    防止进程开启数量过多导致服务器压力过大
    进程池中有两个方法:
      1)apply: 多个进程异步执行,一个一个的执行
      2)apply_async: 多个进程同步执行,同时执行多个进程
    from  multiprocessing import Process,Pool
    import time,os
    def foo(i):
        time.sleep(2)
        print("in the process",os.getpid()) #打印子进程的pid
        return i+100
    
    def call(arg):
        print('-->exec done:',arg,os.getpid())
    
    if __name__ == '__main__':
        pool = Pool(3)                      #进程池最多允许5个进程放入进程池
        print("主进程pid:",os.getpid())     #打印父进程的pid
        for i in range(10):
            #用法1 callback作用是指定只有当Foo运行结束后就执行callback调用的函数,父进程调用的callback函数
            pool.apply_async(func=foo, args=(i,),callback=call)
    
            #用法2 串行 启动进程不在用Process而是直接用pool.apply()
            # pool.apply(func=foo, args=(i,))
    
        print('end')
        pool.close()    #关闭pool
        pool.join()     #进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。

    1.4 僵尸进程

    1)僵尸进程定义
      1、僵尸进程产生的原因就是父进程产生子进程后,子进程先于父进程退出
      2、但是父进程由于种种原因,并没有处理子进程发送的退出信号,那么这个子进程就会成为僵尸进程。

    2)用python写一个僵尸进程

    #!/usr/bin/env python
    #coding=utf8
     
    import os, sys, time
    #产生子进程
    pid = os.fork()
     
    if pid == 0:
        #子进程退出
        sys.exit(0)
    #父进程休息30秒
    time.sleep(30)
    # 先产生一个子进程,子进程退出,父进程休息30秒,那就会产生一个僵尸进程

    ps -ef| grep defunct 在linux下查看僵尸进程

    [root@linux-node4 ~]# ps -ef| grep defunct
    root     110401  96083  0 19:11 pts/2    00:00:00 python defunct.py
    root     110402 110401  0 19:11 pts/2    00:00:00 [python] <defunct>
    root     110406  96105  0 19:11 pts/3    00:00:00 grep --color=auto defunct

    1.5 Python中使用过的进程模块?

    1.5.1 multiprocessing

    1、multiprocessing是一个使用类似于线程模块的API支持产生进程的包。
    2、多处理包提供本地和远程并发,通过使用子进程而不是线程有效地侧向执行全局解释器锁。
    3、因此,多处理模块允许程序员充分利用给定机器上的多个处理器。 它可以在Unix和Windows上运行。
    4、进程池抓取页面
    # -*- coding: utf-8 -*-
    import requests
    from multiprocessing import Pool
    
    def fetch_request(url):
        result = requests.get(url)
        print(result.text)
    
    def call(arg):
        print('-->exec done:',"测试进程池执行后回调功能")
    
    url_list = [
        'https://www.baidu.com',
        'https://www.google.com/',         #google页面会卡住,知道页面超时后这个进程才结束
        'http://dig.chouti.com/',          #chouti页面内容会直接返回,不会等待Google页面的返回
    ]
    
    if __name__ == '__main__':
        pool = Pool(10)        # 创建线程池
        for url in url_list:
            #用法1 callback作用是指定只有当Foo运行结束后就执行callback调用的函数,父进程调用的callback函数
            pool.apply_async(func=fetch_request, args=(url,),callback=call)
        print('end')
        pool.close()    #关闭pool
        pool.join()     #进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。

    1.5.2 concurrent.futures

    1、简介
    1、Python标准库为我们提供了threading和multiprocessing模块编写相应的多线程/多进程代码
    2、但是当项目达到一定的规模,频繁创建/销毁进程或者线程是非常消耗资源的,这个时候我们就要编写自己的线程池/进程池,以空间换时间。
    3、但从Python3.2开始,标准库为我们提供了concurrent.futures模块,它提供了ThreadPoolExecutor和ProcessPoolExecutor两个类,
    4、实现了对threading和multiprocessing的进一步抽象,对编写线程池/进程池提供了直接的支持。
    2、Executor和Future
    1. Executor
    concurrent.futures模块的基础是Exectuor,Executor是一个抽象类,它不能被直接使用。
    
    但是它提供的两个子类ThreadPoolExecutor和ProcessPoolExecutor却是非常有用
    
    我们可以将相应的tasks直接放入线程池/进程池,不需要维护Queue来操心死锁的问题,线程池/进程池会自动帮我们调度。
    2. Future
    Future你可以把它理解为一个在未来完成的操作,这是异步编程的基础,
    
    传统编程模式下比如我们操作queue.get的时候,在等待返回结果之前会产生阻塞,cpu不能让出来做其他事情
    
    而Future的引入帮助我们在等待的这段时间可以完成其他的操作。

    3、concurrent.futures.ProcessPoolExecutor 抓取网页

    import requests
    from concurrent.futures import ProcessPoolExecutor
    
    def fetch_request(url):
        result = requests.get(url)
        print(result.text)
    
    url_list = [
        'https://www.baidu.com',
        'https://www.google.com/',         #google页面会卡住,知道页面超时后这个进程才结束
        'http://dig.chouti.com/',          #chouti页面内容会直接返回,不会等待Google页面的返回
    ]
    
    if __name__ == '__main__':
        pool = ProcessPoolExecutor(10)        # 创建线程池
        for url in url_list:
            pool.submit(fetch_request,url)    # 去线程池中获取一个进程,进程去执行fetch_request方法
        pool.shutdown(wait = True)
        # shutdown相当于一个开关,它会读取程序中所设定的进程总数,直至每开启一个进程,它读取设定的总数就会减一,直至为0时便会打印主线程
  • 相关阅读:
    Codeforces 177G2 Fibonacci Strings KMP 矩阵
    Codeforces Gym100187C Very Spacious Office 贪心 堆
    Codeforces 980F Cactus to Tree 仙人掌 Tarjan 树形dp 单调队列
    AtCoder SoundHound Inc. Programming Contest 2018 E + Graph (soundhound2018_summer_qual_e)
    BZOJ3622 已经没有什么好害怕的了 动态规划 容斥原理 组合数学
    NOIP2016提高组Day1T2 天天爱跑步 树链剖分 LCA 倍增 差分
    Codeforces 555C Case of Chocolate 其他
    NOIP2017提高组Day2T3 列队 洛谷P3960 线段树
    NOIP2017提高组Day2T2 宝藏 洛谷P3959 状压dp
    NOIP2017提高组Day1T3 逛公园 洛谷P3953 Tarjan 强连通缩点 SPFA 动态规划 最短路 拓扑序
  • 原文地址:https://www.cnblogs.com/xiaoxiamiaichiyu/p/14583665.html
Copyright © 2011-2022 走看看