• 《Python》进程收尾线程初识


    一、数据共享

      from multiprocessing import Manager

      把所有实现了数据共享的比较便捷的类都重新又封装了一遍,并且在原有的multiprocessing基础上增加了新的机制list、dict

      机制:支持的数据类型非常有限

        list、dict都不是数据安全的,需要自己加锁来保证数据安全

    from multiprocessing import Manager,Process,Lock
    
    def work(d,lock):
        with lock:
            d['count'] -= 1
    
    if __name__ == '__main__':
        lock = Lock()
        with Manager() as m:   # m = Manager()
            dic = m.dict({'count':100})
            p_lst = []
            for i in range(10):
                p = Process(target=work, args=(dic, lock))
                p_lst.append(p)
                p.start()
            for p in p_lst:
                p.join()
            print(dic)
    #{'count': 90}
    with ......
        一大段语句
    dis模块
    python的上下文管理
    在执行一大段语句之前,自动做某个操作  open
    在执行一大段语句之后,自动做某个操作  close
    
    面向对象的魔术方法(双下杠杠方法)
    # 回调函数 in Pool
    
    import os
    from multiprocessing import Pool
    
    def func(i):
        print('第一个任务', os.getpid())
        return '*'*i
    
    def call_back(res):   #回调函数
        print('回调函数:', os.getpid())
        print('res--->', res)
    
    if __name__ == '__main__':
        p = Pool()
        print('主进程', os.getpid())
        p.apply_async(func, args=(1,), callback=call_back)
        p.close()
      p.join()
     

      func执行完毕之后执行callback函数

      func的返回值会作为callback的参数

      回调函数是在主进程中实现的

      应用场景:子进程有大量运算要做,回调函数等待结果做简单处理

    import re
    from urllib.request import urlopen
    from multiprocessing import Pool
    
    url_lst = [
        'http://www.baidu.com',
        'http://www.sohu.com',
        'http://www.sogou.com',
        'http://www.4399.com',
        'http://www.cnblogs.com',
    ]
    
    def get_url(url):
        response = urlopen(url)
        ret = re.search('www.(.*?).com', url)
        print('%s finished' % ret.group(1))
        return ret.group(1),response.read()
    
    def call(content):
        url,con = content
        with open(url+'.html', 'wb')as f:
            f.write(con)
    if __name__ == '__main__':
        p = Pool()
        for url in url_lst:
            p.apply_async(get_url,args=(url,),callback=call)
        p.close()
        p.join()
    子进程去访问网页子进程去处理网页的结果

    二、线程理论基础

      进程是计算机中最小的资源分配单位,进程对于操作系统来说还具有一定的负担

      创建一个进程,操作系统分配的资源大约有:代码,数据,文件等

    1、为什么要有线程

      线程是轻量级的概念,他没有属于自己的进程资源,一条线程只负责执行代码,没有自己独立的代码、数据以及文件

      线程是计算机中能被CPU调用的最小的单位,当前大部分计算机中的CPU都是执行的线程中的代码

      线程与进程之间的关系:每一个进程中都至少有一条线程在工作

    线程的特点:

      同一个进程中的所有线程的资源是共享的

      轻量级, 没有自己的资源

    进程与线程之间的区别:    

      占用的资源、调度的效率、资源是否共享

    线程的并行问题:

      线程可以并行:java、c++,c#等

      在cpython中,一个进程中的多个线程是不可以并行的

      原因是:Cpython解释器内部有一把全局解释器锁GIL,所以线程不能充分利用多核,同一时刻同一进程中的线程只有一个能被cpu执行

      GIL锁确实是限制了你程序的效率,但目前可以帮助你提高线程之间切换的效率

      如果是想写高计算型的就要多进程或者换一个解释器

    2、threading 模块

    # 并发
    
    import os
    from threading import Thread
    
    def func(i):
        print('子线程:', i, os.getpid())
    
    print('主线程', os.getpid())
    for i in range(10):
        t = Thread(target=func, args=(i,))
        t.start()
    # 进程和线程的差距
    
    import os
    import time
    from threading import Thread
    from multiprocessing import Process
    
    
    def func(i):
        print('子:', os.getpid())
    
    if __name__ == '__main__':
        start = time.time()
        t_lst = []
        for i in range(100):
            t = Thread(target=func, args=(i,))
            t.start()
            t_lst.append(t)
        for t in t_lst:
            t.join()
        end = time.time()-start
    
        start = time.time()
        t_lst = []
        for i in range(100):
            p = Process(target=func, args=(i,))
            p.start()
            t_lst.append(p)
        for p in t_lst:
            p.join()
        end2 = time.time()-start
        print(end, end2)
    #0.0279843807220459 13.582834720611572
    # 线程间的数据共享
    
    from threading import Thread
    
    num = 100
    def func():
        global num
        num -= 1            #每个线程都-1
    
    t_lst = []
    for i in range(100):
        t = Thread(target=func)   #创建一百个线程
        t.start()
        t_lst.append(t)
    for t in t_lst:
        t.join()
    print(num)   #0 

    Thread 类的其他用法

    Thread实例对象的方法
      # isAlive(): 返回线程是否活动的。
      # getName(): 返回线程名。
      # setName(): 设置线程名。
    
    threading模块提供的一些方法:
      # threading.currentThread(): 返回当前的线程变量。
      # threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
      # threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
    from threading import currentThread,Thread
    def func():
        time.sleep(2)
    
    t = Thread(target=func)
    t.start()
    print(t.is_alive())    #True(判断线程是否活着)
    print(t.getName())  #Tread-1
    t.setName('tt')
    print(t.getName())   #tt(改名字)
    
    def func():
        print('子线程:', currentThread().ident)
        time.sleep(2)
    print('主线程:',currentThread().ident)
    t = Thread(target=func)
    t.start()
    #currentThread().ident返回线程的pid
    
    from threading import enumerate
    def func():
        print('子进程:', currentThread().ident)
        time.sleep(2)
    
    print('主进程:', currentThread().ident)
    for i in range(10):
        t = Thread(target=func)
        t.start()
    print(len(enumerate()))
    #enumerate()返回一个包含正在运行的线程的list,len(list)
    
    from threading import activeCount
    def func():
        print('子线程:', currentThread().ident)
        time.sleep(2)
    
    print('主线程:', currentThread().ident)
    for i in range(10):
        t = Thread(target=func)
        t.start()
    print(activeCount())
    #activeCount()返回正在运行的线程数量,与len(threading.enumerate())有相同的结果

    3、守护线程

    import time
    from threading import Thread
    
    def func():
        while True:
            time.sleep(1)
            print(123)
    
    def func2():
        print('func2 start')
        time.sleep(3)
        print('func2 end')
    
    t1 = Thread(target=func)
    t2 = Thread(target=func2)
    t1.setDaemon(True)
    t1.start()
    t2.start()
    print('主线程代码结束')
    # func2 start
    #主线程代码结束
    #123
    #123
    #func2 end

      守护线程 是在主线程代码结束之后,再等待子线程执行结束后才结束

      主线程结束  就意味着主进程结束

      主线程等待所有的线程结束

      主线程结束了以后  守护线程会随着主进程的结束而随之结束  不是随着代码的结束而结束

      

    #################################################################################

    线程
    线程和进程之间的关系
    每个进程内都有一个线程
    线程是不能独立存在的
    线程和进程之间的区别
    同一个进程中线程之间的数据是共享的
    进程之间的数据是隔离的
    线程是被cpu执行的最小单位
    操作系统调度
    进程是计算机中最小的资源分配单位
    python
    GIL锁 全局解释器锁 全局锁
    cpython解释器中的
    锁线程 :同一时刻同一个进程只会有一个线程访问CPU
    锁的是线程而不是数据
    当程序是高IO型的 多线程
    当程序是高计算(CPU)型的 多进程
    cpu*1 ~ cpu*2

    threading
    Thread
    守护线程 :主线程结束之后才结束

    socket_server IO多路复用 + 多线程
    框架 并发的效果 :多线程、协程的概念 flask
    爬虫 :线程池 协程

    set、dict、list
    生成器
    面向对象的进阶 :魔术方法
    管道
    socket_server的源码
  • 相关阅读:
    Javascript设计模式学习(二)封装续
    Javascript设计模式学习(三)更多的高级样式
    【IBM Tivoli Identity Manager 学习文档】1 简介
    【读书笔记】测试驱动开发(中文版)
    【OpenCV学习】利用HandVu进行手部动作识别分析
    【生活】海淀驾校皮卡科目三实际道路考试备考
    【Linux开发技术之工具使用】配置VIM下编程和代码阅读环境
    【英语天天读】叶芝诗歌《当你老了》赏析——特别喜欢的一首诗,水木年华《一生有你》歌词来源
    【SIP协议】学习初学笔记
    【面向对象程序设计之CRC】CRC卡及其应用
  • 原文地址:https://www.cnblogs.com/zyling/p/12789932.html
Copyright © 2020-2023  润新知