不做大哥好多年 不做大哥好多年
首页
  • MySQL
  • Redis
  • Elasticsearch
  • Kafka
  • Etcd
  • MongoDB
  • TiDB
  • RabbitMQ
  • 01.GO基础
  • 02.面向对象
  • 03.并发编程
  • 04.常用库
  • 05.数据库操作
  • 06.Beego框架
  • 07.Beego商城
  • 08.GIN框架
  • 09.GIN论坛
  • 10.微服务
  • 01.Python基础
  • 02.Python模块
  • 03.Django
  • 04.Flask
  • 05.SYL
  • 06.Celery
  • 10.微服务
  • 01.Java基础
  • 02.面向对象
  • 03.Java进阶
  • 04.Web基础
  • 05.Spring框架
  • 100.微服务
  • Docker
  • K8S
  • 容器原理
  • Istio
  • 数据结构
  • 算法基础
  • 算法题分类
  • 前置知识
  • PyTorch
  • 01.Python
  • 02.GO
  • 03.Java
  • 04.业务问题
  • 05.关键技术
  • 06.项目常识
  • 10.计算机基础
  • Linux基础
  • Linux高级
  • Nginx
  • KeepAlive
  • ansible
  • zabbix
  • Shell
  • Linux内核

逍遥子

不做大哥好多年
首页
  • MySQL
  • Redis
  • Elasticsearch
  • Kafka
  • Etcd
  • MongoDB
  • TiDB
  • RabbitMQ
  • 01.GO基础
  • 02.面向对象
  • 03.并发编程
  • 04.常用库
  • 05.数据库操作
  • 06.Beego框架
  • 07.Beego商城
  • 08.GIN框架
  • 09.GIN论坛
  • 10.微服务
  • 01.Python基础
  • 02.Python模块
  • 03.Django
  • 04.Flask
  • 05.SYL
  • 06.Celery
  • 10.微服务
  • 01.Java基础
  • 02.面向对象
  • 03.Java进阶
  • 04.Web基础
  • 05.Spring框架
  • 100.微服务
  • Docker
  • K8S
  • 容器原理
  • Istio
  • 数据结构
  • 算法基础
  • 算法题分类
  • 前置知识
  • PyTorch
  • 01.Python
  • 02.GO
  • 03.Java
  • 04.业务问题
  • 05.关键技术
  • 06.项目常识
  • 10.计算机基础
  • Linux基础
  • Linux高级
  • Nginx
  • KeepAlive
  • ansible
  • zabbix
  • Shell
  • Linux内核
  • Python

    • 01.进程
      • 01.进程
        • 1.1 什么是进程?
        • 1.2 进程如何通信?
        • 1.3 为什么需要进程池?
        • 1.4 僵尸进程
        • 1.5 Python中使用过的进程模块?
        • 1.5.1 multiprocessing
        • 1.5.2 concurrent.futures
    • 02.线程
    • 03.协程
    • 04.select、poll、epoll
    • 05.装饰器
    • 06.生成器和迭代器
    • 07.面向对象
    • 08.深浅拷贝
    • 09.垃圾回收
    • 10.上下文管理
    • 11.高阶函数
    • 12.次重点
  • GO

  • Java

  • 业务问题

  • 关键技术

  • 项目常识

  • 计算机基础

  • 常识
  • Python
xiaonaiqiang
2021-02-09
目录

01.进程

# 01.进程

# 1.1 什么是进程?

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

# 1.2 进程如何通信?

  • 同一程序下进程通信
    • 进程queue(父子进程通信)
    • pipe(同一程序下两个进程通信)
    • managers(同一程序下多个进程通信)
  • Java项目和python项目如何通信
    • 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 1.4 僵尸进程

  • 1)僵尸进程定义

      1. 僵尸进程产生的原因就是父进程产生子进程后,子进程先于父进程退出
      1. 但是父进程由于种种原因,并没有处理子进程发送的退出信号,那么这个子进程就会成为僵尸进程。
  • 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秒,那就会产生一个僵尸进程
1
2
3
4
5
6
7
8
9
10
11
12
13
  • 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
      2
      3
      4

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

# 1.5.1 multiprocessing

  • multiprocessing是一个使用类似于线程模块的API支持产生进程的包。
  • 多处理包提供本地和远程并发,通过使用子进程而不是线程有效地侧向执行全局解释器锁。
  • 因此,多处理模块允许程序员充分利用给定机器上的多个处理器。 它可以在Unix和Windows上运行。
  • 进程池抓取页面
# -*- 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 1.5.2 concurrent.futures

  • 1、简介 参考官网 (opens new window)

    • 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时便会打印主线程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
上次更新: 2025/2/25 11:09:45
02.线程

02.线程→

最近更新
01
04.数组双指针排序_子数组
03-25
02
08.动态规划
03-25
03
06.回溯算法
03-25
更多文章>
Theme by Vdoing | Copyright © 2019-2025 逍遥子 技术博客 京ICP备2021005373号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式