zoukankan      html  css  js  c++  java
  • threading.local()方法;线程池

    一,threading.local()

    import time
    import threading
    
    v = threading.local()
    
    def func(arg):
        # 内部会为当前线程创建一个空间用于存储:phone=自己的值
        v.phone = arg
        time.sleep(2)
        print(v.phone,arg) # 去当前线程自己空间取值
    
    for i in range(10):
        t =threading.Thread(target=func,args=(i,))
        t.start()

    threading.local()这个方法的特点用来保存一个全局变量,但是这个全局变量只有在当前线程才能访问,

    v.phone = arg这条语句可以储存一个变量到当前线程,如果在另外一个线程里面再次对v.phone = arg
    进行赋值,那么会在另外一个线程单独创建内存空间来存储,也就是说在不同的线程里面赋值 不会覆盖之前的值,因为每个

    线程里面都有一个单独的空间来保存这个数据,而且这个数据是隔离的,其他线程无法访问

    应用场景

    这个东西可以用在那些地方呢,比如下载,现在都是多线程下载了,就像酷狗那样,可以同时下载很多首歌曲,那么

    就可以利用这个方法来保存每个下载线程的数据,比如下载进度,下载速度之类的

    所以  如果你在开发多线程应用的时候  需要每个线程保存一个单独的数据供当前线程操作,可以考虑使用这个方法,简单有效

    其实这样的功能还有很多种方法可以实现,比如我们在主线程实例化一个dict对象,然后用线程的名字作为key,因为线程之间可以共享数据,

    所以也可以实现相同功能,并且灵活性更多,不过代码就没那么优雅简洁了

    二,threading.local()原理

    import time
    import threading
    
    DATA_DICT = {}
    
    def func(arg):
        ident = threading.get_ident()
        DATA_DICT[ident] = arg
        time.sleep(1)
        print(DATA_DICT[ident],arg)
    
    
    for i in range(10):
        t =threading.Thread(target=func,args=(i,))
        t.start()

    三.线程池

    py2没有py3才有的

    对于任务数量不断增加的程序,每有一个任务就生成一个线程,最终会导致线程数量的失控,例如,整站爬虫,假设初始只有一个链接a,那么,这个时候只启动一个线程,运行之后,得到这个链接对应页面上的b,c,d,,,等等新的链接,作为新任务,这个时候,就要为这些新的链接生成新的线程,线程数量暴涨。在之后的运行中,线程数量还会不停的增加,完全无法控制。所以,对于任务数量不断增加的程序,固定线程数量的线程池是必要的。

     创建线程池:、

    from concurrent.futures import ThreadPoolExecutor
    import time
    
    def task(a1,a2):
        time.sleep(2)
        print(a1,a2)
    
    # 创建了一个线程池(最多5个线程)
    pool = ThreadPoolExecutor(5)
    
    for i in range(40):
        # 去线程池中申请一个线程,让线程执行task函数。
        pool.submit(task,i,8)

    线程与线程池的对比

    ######## 线程 ###############
    import time
    import threading
    
    def task(arg):
        time.sleep(50)
    
    while True:
        num = input('>>>')
        t = threading.Thread(target=task,args=(num,))
        t.start()
    
    ######### 线程池 ############
    import time
    from concurrent.futures import ThreadPoolExecutor
    
    def task(arg):
        time.sleep(50)

    # 可以控制最多创建的线程

    四,生产者消费者模型

    解决了不用一直等待的问题

    import time
    import queue
    import threading
    q = queue.Queue() # 队列,线程安全的
    
    def producer(id):
        """
        生产者
        :return:
        """
        while True:
            time.sleep(2)
            q.put('包子')
            print('厨师%s 生产了一个包子' %id )
    
    for i in range(1,4):
        t = threading.Thread(target=producer,args=(i,))
        t.start()
    
    
    def consumer(id):
        """
        消费者
        :return:
        """
        while True:
            time.sleep(1)
            v1 = q.get()
            print('顾客 %s 吃了一个包子' % id)
    
    for i in range(1,3):
        t = threading.Thread(target=consumer,args=(i,))
        t.start()
       # 生产者消费者模型解决了什么问题?不用一直等待的问题

     

  • 相关阅读:
    实验 4:Open vSwitch 实验——Mininet 中使用 OVS 命令
    实验 3:Mininet 实验——测量路径的损耗率
    软工第一次作业
    实验2:Mininet实验——拓扑的命令脚本生成
    实验 1:Mininet 源码安装和可视化拓扑工具
    AU降噪处理
    软件测试,Homework3
    软件测试,Lab1
    软件测试,Homework2
    node.js,同时访问出错,Can't set headers after they are sent
  • 原文地址:https://www.cnblogs.com/zwq-/p/9629758.html
Copyright © 2011-2022 走看看