进程和并发

咱们已经讲过了什么是线程,那今天就来学习一下什么是进程,**进程(Process)**是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操做系统结构的基础。 进程是正在运行的程序的实例,简单的说就是好比咱们本身在python文件中写了一些代码,这叫作程序,而运行这个python文件的时候就叫作进程html

什么是并发

那什么是并发呢,并发就是在某个时间段内,两件或两件以上的事件轮流交替使用某一资源,其目的是提升效率; 须要注意的是并发和并行的区别:python

  • 并发是指两个或多个事件在同一时间间隔发生,并行是指两个或者多个事件在同一时刻发生;
  • 并发是在同一实体上的多个事件,并行是在不一样实体上的多个事件;

multiprocess模块

Python中提供multiprocess模块实现多进程并发,咱们来看一下multiprocess模块的使用,经过一个实例来对比多线程和多进程程序运行对CPU的使用状况linux

import multiprocessing
import threading

def worker():
    number = 0
    for i in range(10000000):
        number += 1
        print('循环次数:{} number:{}'.format(i+1, number))

if __name__ == '__main__':
    for i in range(4):
        # 建立线程
        threading.Thread(target=worker, name='thread worker {}'.format(i)).start()

        # 建立进程
        multiprocessing.Process(target=worker, name='process worker {}'.format(i)).start()

分别启动线程和进程,运行代码,查看电脑的CPU的使用率,发现多进程占用内存多,切换复杂,CPU利用率低,多线程占用内存少,切换简单,CPU利用率高;多线程

进程的一些对象方法并发

import multiprocessing
import threading
import time

def worker():
    number = 0
    for i in range(10000000):
        number += 1
        time.sleep(0.1)
        print(multiprocessing.current_process().name)  # 获取当前进程的名称
        print('循环次数:{} number:{}'.format(i+1,number ))
        
if __name__ == '__main__':
    for i in range(4):
        process = multiprocessing.Process(target=worker, name='process worker {}'.format(i))
        process.start()
        print(process.pid) # 获取进程的pid
        print(process.exitcode) # 获取退出状态码
        print(process.name)  # 获取进程名称
        time.sleep(30)
        print(process.terminate()) # 终止进程
  • multiprocessing支持子进程、通讯和共享数据、执行不一样形式的同步,提供了ProcessQueuePipeLock等 组件;函数

  • 可使用multiprocessing.Process对象来建立一个进程,该进程能够运行在Python程序内部编写的函数;学习

  • process模块是一个建立进程的模块,借助这个模块,就能够完成进程的建立,有start()run()join()的方法;fetch

进程并发:concurrent模块

from concurrent.futures import ProcessPoolExecutor
import requests

def fetch_url(url):
    result = requests.get(url=url, )
    return result.text
if __name__ == '__main__':
    # 建立10个线程队列的线程池
    pool = ProcessPoolExecutor(10)
    # 获取任务返回对象
    a = pool.submit(fetch_url, 'http://www.baidu.com')
    # 取出返回的结果
    x = a.result()
    print(x)

也可使用上下文管理的方式url

from concurrent.futures import ProcessPoolExecutor
import requests

def fetch_url(url):
    result = requests.get(url=url, )
    return result.text
if __name__ == '__main__':
    with ProcessPoolExecutor(max_workers=10) as pool:
        a = pool.submit(fetch_url, 'http://www.9xkd.com')
        print(a.result())
  • concurrent模块可以提供一个future的实例对象,实例对象提供了线程的执行器和进程的执行器;操作系统

  • submit():返回一个Future对象;

  • result():查看调用的返回结果;

  • done():若是任务成功执行或任务取消返回True;

  • cancel():取消任务;

  • running():若是任务正在执行返回True;

  • exception(): 获取执行抛出的异常;

守护进程实现(POSIX兼容)

  • 在linux或者unix操做系统中,守护进程(Daemon)是一种运行在后台的特殊进程,它独立于控制终端而且周期 性的执行某种任务或等待处理某些发生的事件;

  • 因为在linux中,每一个系统与用户进行交流的界面称为终端,每个今后终端开始运行的进程都会依附于这个终 端,这个终端被称为这些进程的控制终端,当控制终端被关闭的时候,相应的进程都会自动关闭;

  • 可是守护进程却能突破这种限制,它脱离于终端而且在后台运行,而且它脱离终端的目的是为了不进程在运 行的过程当中的信息在任何终端中显示而且进程也不会被任何终端所产生的终端信息所打断,它从被执行的时候 开始运转,直到整个系统关闭才退出;

守护进程实现的步骤:

  • 父进程fork出子进程并exit退出;

  • 子进程调用setsid建立新会话;

  • 子进程调用系统函数chdir将根目录"/"成为子进程的工做目录;

  • 子进程调用系统函数umask将该进程的umask设置为0;

  • 子进程关闭从父进程继承的全部不须要的文件描述符;

对 os.fork( )的理解:

  • os.fork()返回两个值,一个是在当前父进程返回的,一个是在子进程中返回的;

  • 子进程返回的是0,父进程返回的是子进程的pid;

import os
pid = os.fork()
print(pid)
if pid == 0:
    print("我是子进程 pid={}, parent_pid={}".format(os.getpid(), os.getppid()))
else:
    print("我是父进程 pid={}, parent_pid={}".format(os.getpid(), os.getppid()))

参考:https://www.9xkd.com/user/plan-view.html?id=1923439230

相关文章
相关标签/搜索