• day33 线程以及线程池


    今日内容以及未来的计划:

      1、并发编程需要掌握的知识点:

      开启进程/线程

      生产者消费者模型!!!(后面讲)

      GIL全局解释器锁(进程与线程的区别和应用场景)

      进程池线程池

      10模型(理论)

    2、多线程

        线程vs进程

        GIL全局解释器锁

        线程池

    二、新内容:

    1、(1)进程只是把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程才是CPI上的执行单位

      (2)线程相当于流水线(一条具体的地铁线路),进程是指的资源(北京地铁)

      (3)改变主线程会影响其他线程(因为线程是共享资源)

        改变主进程不会影响其他子进程(空间是隔离的,执行也是互不影响的)

      (4)子线程改变同样会影响主线程

    2、为什么要使用多线程

    3、多线程

      (1)线程的概念?—————

        一个进程内默认就会有一个控制线程,该控制线程可以执行代码从而创建新的线程

        该控制线程的执行周期就代表改进程的执行周期

      (2)线程VS进程

        1、线程的创建开销小于进程,创建速度快

        2、同一进程下的多个线程共享该进程的地址空间

      GIL全局解释器锁

      线程池

    4、开启线程的两个方式(为了使任务并发)

      有两个线程(主线程,子线程(t.start()))

      线程的开启速度快(开销小)

      (1)线程开启的第一种方式

    from threading import Thread
    import time,os
    
    def task():
        print("%s is running"%os.getpid())
        time.sleep(2)
        print("%s is done"%os.getpid())
    if __name__=="__main__":
        t=Thread(target=task,)
        t.start()
        print("")
    开启线程的方式一
    from threading import Thread
    from  multiprocessing import Process
    import time,os
    def task():
        print("%s is running"%os.getpid())
        time.sleep(2)
        print("%s is done"%os.getpid())
    class Mythread(Thread):
        def __init__(self,name):
            super().__init__()
            self.name=name
        def run(self):
            print("%s is running"%os.getpid())
            time.sleep(5)
            print("%s is done"%os.getpid())
    if __name__=="__main__":
        t=Mythread("xxxx")
        t.start()
        print("")
    开启线程的方式二

     总结:  

      (1)一个进程内不开子进程也不开“子线程”,主线程结束,该进程就结束

      (2)当一个进程内开启子进程时:

         主线程结束,主进程要等,等所有子进程运行完毕,给儿子收尸

      (3)当一个进程内开启多个线程时;

        主线程结束并不意味着看进程结束;

        进程的结束指的是该进程内所有的线程都运行完毕,才应该回收进程

    5、ID号的说明  

    from threading import Thread
    from multiprocessing import Process
    import time,os
    def task():
        print("partent,%s self,%s"%(os.getpid(),os.getpid()))
        time.sleep(2)
    if __name__=="__main__":
        t=Thread(target=task,)
        # t=Process(target=task(),)
        t.start()
        print("",os.getpid(),os.getpid())
    开启进程和开启线程的id说明

    6、开子进程需要申请空间

     (1)进程之间内存空间隔离

       线程之间内存空间隔离

    from threading import Thread
    from multiprocessing import Process
    import time,os
    n=100
    def task():
        global n
        n=0
    if __name__=="__main__":
        t=Thread(target=task,)  #线程之间内存空间共享
        # t=Process(target=task,) #进程之间内存空间隔离
        t.start()
        t.join()
        print("",n)
    进程和线程 进行验证

    7、了解部分  

      用来调试线程,查看是哪一条线程(测试时会用到) 

    # 用来调试线程,查看是哪一条线程(测试时会用到)
    from threading import  Thread,current_thread
    import time,os
    def task():
        print("%s is running"%current_thread().getName())
        time.sleep(5)
        print("%s is done"%current_thread().getName())
    if __name__=="__main__":
        t=Thread(target=task,name="xxx")
        t=Thread(target=task,)
        t=Thread(target=task,)
        t.start()
        # print(t.name)
        print("",current_thread().getName())
    View Code

    查看当前活着的线程

    # 用来调试线程,查看是哪一条线程(测试时会用到)
    from threading import  Thread,current_thread,enumerate,active_count
    import time,os
    def task():
        print("%s is running"%current_thread().getName())
        time.sleep(1)
        print("%s is done"%current_thread().getName())
    if __name__=="__main__":
        t=Thread(target=task,name="xxx")
        t=Thread(target=task)
        t.start()
        # print(t.name)
        print("",current_thread().getName())
    #   查看当前活着的线程
        print(enumerate()[0].getName())
        print(active_count())
        print("",current_thread().getName())
    查看当前活着的线程

    8、线程池

    from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
    from threading import current_thread
    import time,random
    def task():
        print("%s is running"%current_thread().getName())
        time.sleep(random.randint(1,3))
    if __name__=="__main__":
        # t=ProcessPoolExecutor() 默认cpu的核数
        # import os
        # print(os.cpu_count())
    
        t=ThreadPoolExecutor(3)
        for i in range(10):
            t.submit(task,)
        t.shutdown(wait=True)
        print("",current_thread().getName())
    线程池
    from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
    from threading import current_thread
    import time,random
    def task(n):
        print("%s is running"%current_thread().getName())
        time.sleep(random.randint(1,3))
        return n**2
    if __name__=="__main__":
        # t=ProcessPoolExecutor() 默认cpu的核数
        # import os
        # print(os.cpu_count())
    
        t=ThreadPoolExecutor(3) #默认是cpu的核数*5
    
        objs=[]
        for i in range(10):
            obj=t.submit(task,i)
            objs.append(obj)
        t.shutdown(wait=True)
        for obj in objs:
            print(obj.result())
        print("",current_thread().getName())
    线程池取用结果

    9、什么时候用池:用量大的时候

      什么时候时候用进程  什么时候用线程

    10、补充异步的概念

      爬虫中的应用

      (1)串着爬取:   

    #pip install resquests
    import requests
    from threading import current_thread
    urls=[
        "https://www.python.org",
        "https://www.baidu.com",
        "https://www.tmall.com",
    ]
    def get(url):
        print("%s GET %s"%(current_thread().getName(),url))
        response=requests.get(url)
        if response.status_code==200:
            return {"url":url,"text":response.text}
    def parse(res):
        print("%s parse %s"%(current_thread().getName(),res["url"]))
        print("[%s] parse res[%s]"%(res["url"],len(res["text"])))
    
    for url in urls:
        res=get(url)
        parse(res)
    View Code

    使用正则: 

    #pip install resquests
    import requests
    from threading import current_thread
    urls=[
        "https://www.python.org",
        "https://www.baidu.com",
        "https://www.tmall.com",
    ]
    def get(url):
        print("%s GET %s"%(current_thread().getName(),url))
        response=requests.get(url)
        if response.status_code==200:
            return {"url":url,"text":response.text}
    def parse(res):
        # print("%s parse %s"%(current_thread().getName(),res["url"]))
        # print("[%s] parse res[%s]"%(res["url"],len(res["text"])))
        print("[%s] <%s> (%s)"%(current_thread().getName(),res["url"],len(res["text"])))
    for url in urls:
        res=get(url)
        parse(res)
    View Code

    (2)开发爬取 异步的方式提交

      爬虫是下载耗时,解析的时间是可以忽略不计的

    #pip install resquests
    import requests
    from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
    from threading import current_thread
    import time
    import os
    
    def get(url):
        print("%s GET %s"%(os.getpid(),url))
        response=requests.get(url)
        time.sleep(3)
        if response.status_code==200:
            return {"url":url,"text":response.text}
    def parse(obj):
        res=obj.result()
        print("[%s] <%s> (%s)"%(os.getpid(),res["url"],len(res["text"])))
    if __name__=="__main__":
        urls=[
            "https://www.python.org",
            "https://www.baidu.com",
            "https://www.tmall.com",
        ]
        t=ProcessPoolExecutor(2)
        for url in urls:
            t.submit(get,url).add_done_callback(parse)
        t.shutdown(wait=True)
        print("",os.getpid())
    回调函数

     下节课继续完善

    # pip install requests
    import requests
    from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
    from threading import current_thread
    import time
    import os
    
    def get(url):
        print('%s GET %s' %(current_thread().getName(),url))
        response=requests.get(url)
        time.sleep(3)
        if response.status_code == 200:
            return {'url':url,'text':response.text}
    
    def parse(obj):
        res=obj.result()
        print('[%s] <%s> (%s)' % (current_thread().getName(), res['url'],len(res['text'])))
    
    if __name__ == '__main__':
        urls = [
            'https://www.python.org',
            'https://www.baidu.com',
            'https://www.jd.com',
            'https://www.tmall.com',
        ]
        t=ThreadPoolExecutor(2)
        for url in urls:
            t.submit(get,url).add_done_callback(parse)
        t.shutdown(wait=True)
    
        print('',os.getpid())
    View Code

     

  • 相关阅读:
    超实用的 Nginx 极简教程,覆盖了常用场景(转)
    阿里云Redis开发规范(转)
    什么是 AQS ?
    缓存穿透、缓存并发、缓存失效之思路变迁(转)
    看不懂JDK8的流操作?5分钟带你入门(转)
    Redis 分布式锁的正确实现方式(转)
    urllib-Proxy
    基本urllib库
    Windows DOS 命令(持续更新...)
    java 位运算符
  • 原文地址:https://www.cnblogs.com/number1994/p/8177202.html
Copyright © 2020-2023  润新知