zoukankan      html  css  js  c++  java
  • 14.效率利器之多线程和线程池

    单线程和多线程:

    怎么来理解线程?在这里举个通俗的例子,便于记忆。

    一张圆桌上面有十碗饭,假如一个人吃一碗饭的时间为1min,那么吃完这一桌需要10min

    (这里一个人我们将他认为成一个线程)

    假如我设定五个人同时开始吃这桌饭,那么吃完这一桌需要大约为1*2=2min

    假如我设定十个人同时开始吃这桌饭,那么吃完这一桌需要大约为1min

    这里为什么多线程的时候会加上大约 这里会涉及到资源抢夺的问题 暂且不管。

    通过上面的例子,我们了解多线程能大大的提高程序的效率。

    那么在代码中怎么实现呢?

    首先我们要了解Python中队列的用法:

    队列的三种实现方法有:

          1、FIFO先入先出队列(Queue)

          2、LIFO后入先出队列(LifoQueue)

          3、优先级队列(PriorityQueue)

    这里用到的是Queue

    import queue   q = queue.Queue()  /  from queue import Queue   q = Queue()
    
    q.qsize()  # 返回当前队列包含的消息数量
    q.empty()  # 如果队列为空返回True 反之False
    q.full()  # 如果队列满了,返回True 反之False
    q.get()  # 获取队列,timeout等待时间  get(self, block=True,timeout=None) block表示是否等待 timeout表示等待多久
    q.put(item)  # 写入队列 put(self, item, block=True,timeout=None) block表示是否等待 timeout表示等待多久
    q.get_nowait()  # 相当于q.get(False) 获取不等待
    q.put_nowait()  # 相当于 q.put(item,False) 写入不等待
    q.task_done()  # 在完成一项工作之后,使用这个方法可以向队列发送一个信号,表示该任务执行完毕
    q.join()  # 等待队列中所有任务(数据)执行完毕之后再往下执行,否则一直等待
    注意点 :join是判断的依据。不单单指的是队列中没有数据,数据get出去之后,要使用task_done向队列发送一个信号,表示该任务执行完毕
    /数据使用完毕

    接下来我们要清楚线程的个数 怎么来设置的 并且里面的参数如何传递。

    from threading import Thread
    from queue import Queue
    q = Queue()
    
    def GetData(q,index):
        # 判断队列是否为空,空则退出while循环
        while q.empty() is False:
            # 打印信息
            print('next:' + str(q.qsize()) + 'index:'+str(index))
            # 将米饭从队列里拿出来
            rice = q.get()
    
            # 之后就可以对这100碗米饭进行五个线程的处理了
            # 比如:requests请求...
    
    
            # 表明该线程完成 发出个成功的消息
            q.task_done()
    # 1 - 100 一共100碗米饭放到这个队列里去
    for rice in range(1,101):
        q.put(rice)
    
    # 遍历循环5次 代表设置5个线程
    for index in range(5):
        """
        target目标  为线程要去做什么事情?
          args参数  需要传递的参数
        """
        # 这里目标 设置成一个函数
        # 将整个队列作为参数 和 线程的下标 传进去
        thread = Thread(target=GetData, args=(q,index,))
        # 不设置为守护线程
        thread.setDaemon(False)
        # 线程开始
        thread.start()
        
    # 等待队列中所有任务(数据)执行完毕之后再往下执行,否则一直等待
    q.join()

    线程池的用法:

    其实与多线程的目的一致,都是为了实现同样的结果,只是路子不一样罢了。

    我们看看线程池的用法:

    from concurrent.futures import ThreadPoolExecutor, as_completed
    
    def handle_true(j):
        print(j)
        pass
    
    # 创建一个线程池 它的工作量为10 即10个线程
    threadpool = ThreadPoolExecutor(max_workers=10)
    
    future_list = []
    # 相同的100碗米饭
    for j in range(1,101):
        # 这里注意 for 10次之后,10个线程任务分配完成。
        # for第11次开始的时候,是上10个线程中的某一个结束的时候
        # 以此类推
        future = threadpool.submit(handle_true,j)
        future_list.append(future)
    # 阻塞器的功能,等待线程任务结束,不然就一直阻塞。
    for future in as_completed(future_list):
        data_list_fin = future.result()  # 线程运行结果
        print('ERROR:', future.exception())  # 查看线程的异常,没有返回None
        print(f"线程结束")
    线程和线程池 整体的结构和思想差不多就结束了 其余变化的都是形式
    可以多试着写几遍 便能拨开云雾

    结束。


  • 相关阅读:
    SP笔记:交叉实现七行并成一行
    HTML tag 学习
    操作哈希表
    Efficient bipedal robots based on passivedynamic walkers
    Pushing People Around
    ZEROMOMENT PONTTHIRTY FIVE YEARS OF ITS LIFE

    Active Learning for RealTime Motion Controllers
    Accelerometerbased User Interfaces for the Control of a Physically Simulated Character
    Dynamic Response for Motion Capture Animation
  • 原文地址:https://www.cnblogs.com/zhouA/p/15741518.html
Copyright © 2011-2022 走看看