zoukankan      html  css  js  c++  java
  • 进程相关

    一.进程和线程的区别 或者GIL锁

      1.进程是cpu资源分配的最小单元

       线程是cpu计算的最小单元

      2.一个进程中可以有多个线程

      3.对于python来说他的进程和线程和其他语言有差异, 是有GIL锁.

       GIL锁保证一个进程中同一时刻只有一个线程被cpu调度.

      IO密集型操作可以使用多线程, 计算密集型操作可以使用多进程.

    二.进程

      进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。

      操作系统引入进程的概念的原因

    从理论角度看,是对正在运行的程序过程的抽象;

    从实现角度看,是一种数据结构,目的在于清晰地刻画动态系统的内在规律,有效管理和调度进入计算机系统主存储器运行的程序。

     进程的特征
    动态性:进程的实质是程序在多道程序系统中的一次执行过程,进程是动态产生,动态消亡的。
    并发性:任何进程都可以同其他进程一起并发执行
    独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位;
    异步性:由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推进
    结构特征:进程由程序、数据和进程控制块三部分组成。
    多个不同的进程可以包含相同的程序:一个程序在不同的数据集里就构成不同的进程,能得到不同的结果;但是执行过程中,程序不能发生改变。
     进程与程序的区别
    程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。
    而进程是程序在处理机上的一次执行过程,它是一个动态的概念。
    程序可以作为一种软件资料长期存在,而进程是有一定生命期的。
    程序是永久的,进程是暂时的。

      进程间的数据不共享

    1.进程间的通信应该尽量避免共享数据的方式

    2.进程间的数据是独立的,可以借助队列或管道实现通信,二者都是基于消息传递的。虽然进程间数据独立,但可以用过Manager实现数据共享

    import multiprocessing
    data_list = []
    def task(arg):
        data_list.append(arg)
        print(data_list)
    def run():
        for i in range(10):
            p = multiprocessing.Process(target=task, args=(i,))
            # p = threading.Thread(target=task,args=(i,))
            p.start()
    if __name__ == '__main__':
        run()
    #结果
      [2]
      [0]
      [1]
      [3]
      [8]
      [5]
      [6]
      [7]
      [4]
      [9]

    进程的常用功能

      join    

        无参数,让主线程在这里等着,等到子线程t1执行完毕,才可以继续往下走
        有参数,让主线程在这里最多等待n秒,无论是否执行完毕,会继续走下去

      deamon    设置为后台线程或前台线程(默认)
                        如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,均停止
                        如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止

      name    

        setName      为线程设置名称

        getName      获取线程名称

      multiprocessing.current_process()      获取当前执行该函数的线程的对象

      multiprocessing.current_process().ident/pid     获取当前执行该函数的线程的ID

    import time
    import multiprocessing
    def task(arg):
        p = multiprocessing.current_process()
        print(p.name)
        time.sleep(2)
        print(arg)
    def run():
        print('111111111')
        p1 = multiprocessing.Process(target=task,args=(1,))
        p1.name = 'pp1'
        p1.start()
        print('222222222')
        p2 = multiprocessing.Process(target=task, args=(2,))
        p2.name = 'pp2'
        p2.start()
        print('333333333')
    if __name__ == '__main__':
        run()
    #结果:111111111
         222222222
       333333333
       pp1
       pp2
       1
       2    

    通过类继承方式创建进程

    import multiprocessing
    class MyProcess(multiprocessing.Process):
        def run(self):
            print('当前进程',multiprocessing.current_process())
    def run():
            p1 = MyProcess()
            p1.start()
            p2 = MyProcess()
            p2.start()
    if __name__ == '__main__':
        run()
    #结果:当前进程 <MyProcess(MyProcess-1, started)>
         当前进程 <MyProcess(MyProcess-2, started)>

    进程间的数据共享

      进程之间的通信有两种实现方式:管道和队列

    
    
    from multiprocessing import Manager,Process,Lock
    def work(dic,mutex):
        # mutex.acquire()
        # dic['count']-=1
        # mutex.release()
        # 也可以这样加锁
       with mutex:
            dic['count'] -= 1
    if __name__ == '__main__':
        mutex = Lock()
        m = Manager()  #实现共享,由于字典是共享的字典,所以得加个锁
        share_dic = m.dict({'count':100})
        p_l = []
        for i in range(100):
            p = Process(target=work,args=(share_dic,mutex))
            p_l.append(p)  #先添加进去
            p.start()
        for i in p_l:
            i.join()
        print(share_dic)
     # 共享就意味着会有竞争,

    三.进程锁

      Lock

      RLock  (一次放一个)( 递归锁 )

      BoundedSemaphore(1次放N个)信号量

      条件(Condition)(1次放动态N个)

      事件Event(1次放所有)

    import time
    import threading
    import multiprocessing
    lock = multiprocessing.RLock()
    def task(arg):
        print('鬼子来了')
        lock.acquire()
        time.sleep(2)
        print(arg)
        lock.release()
    if __name__ == '__main__':
        p1 = multiprocessing.Process(target=task, args=(1,))
        p1.start()
        p2 = multiprocessing.Process(target=task, args=(2,))
        p2.start()

    为什么要加锁

      因数据共享

    四.进程池

    在利用Python进行系统管理的时候,特别是同时操作多个文件目录,或者远程控制多台主机,并行操作可以节约大量的时间。多进程是实现并发的手段之一,需要注意的问题是:

    1. 很明显需要并发执行的任务通常要远大于核数
    2. 一个操作系统不可能无限开启进程,通常有几个核就开几个进程
    3. 进程开启过多,效率反而会下降(开启进程是需要占用系统资源的,而且开启多余核数目的进程也无法做到并行)

    那么什么是进程池呢?  进程池就是控制进程数目

    创建进程池的类:如果指定numprocess为3,则进程池会从无到有创建三个进程,然后自始至终使用这三个进程去执行所有任务,不会开启其他进程

    import time
    from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
    def task(arg):
        time.sleep(2)
        print(arg)
    if __name__ == '__main__':
        pool = ProcessPoolExecutor(5)
        for i in range(10):
            pool.submit(task,i)

    五.初始爬虫

      1.安装:

        pip3 install requests

        pip3 install beautifulsoup4

    import requests
    from bs4 import BeautifulSoup
    from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
    # 模拟浏览器发送请求
    # 内部创建 sk = socket.socket()
    # 和抽屉进行socket连接 sk.connect(...)
    # sk.sendall('...')
    # sk.recv(...)
    def task(url):
        print(url)
        r1 = requests.get(
            url=url,
            headers={
                'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.92 Safari/537.36'
            }
        )
        # 查看下载下来的文本信息
        soup = BeautifulSoup(r1.text, 'html.parser')
        print(soup.text)
        content_list = soup.find('div',attrs={'id':'content-list'})
        for item in content_list.find_all('div',attrs={'class':'item'}):
            title = item.find('a').text.strip()
            target_url = item.find('a').get('href')
            print(title,target_url)
    def run():
        pool = ThreadPoolExecutor(5)
        for i in range(1, 50):
            pool.submit(task, 'https://dig.chouti.com/all/hot/recent/%s' % i)
    if __name__ == '__main__':
        run()
    示例

     相关:

      a.以上示例进程和线程哪个好?
        线程好

      b.requests 模块模拟浏览器发送请求

        本质 requests.get():

          创建socket客户端

          连接 (阻塞)

          发送请求

          接收请求 (阻塞)

          断开连接

      c.线程和进程池

  • 相关阅读:
    Java反射
    浅谈page,request,session,application四种范围
    使用MySQL连接池
    SQL注入漏洞的演示及解决办法
    JDBC工具类的提取
    JDBC使用过程
    MYSQL常用函数
    MySQL数据操作
    MySQL存储引擎
    Python核心技术与实战——六|异常处理
  • 原文地址:https://www.cnblogs.com/chenxi67/p/9636088.html
Copyright © 2011-2022 走看看