python 多线程知识全面解析

Python编程学堂 4天前

非阻塞启动线程

    import threadingimport timedef one_thread(name,id):    print("start....")    print(name)    print(id)    time.sleep(5)    print("end...")print("start thread")threading.Thread(target=one_thread, args=(), kwargs={"name": 111, "id": 222}).start()# args是一个list# kwargs是一个字典,需要对应函数的keyprint("end thread")
    • 得到值如下,线程启动函数后,非阻塞执行

      start threadstart....111222end threadend...

      多线程并发处理

        import threadingimport timeclass myThread(threading.Thread):    def __init__(self, threadID, name):        threading.Thread.__init__(self)        self.threadID = threadID        self.name = name    def run(self):        print_time(self.threadID, self.name)num = 0def print_time(threadID, name):    global num    # 每一个线程循环10次,最终总循环次数为30次    for i in range(10):        print("start run")        time.sleep(2)        print(i)        num += 1    print("thread_id=%s:name=%s" % (threadID, name))if __name__ == '__main__':    threads = []    # 新增三个线程    for i in range(3):        name = "Thread-%d" % i        t = myThread(i, name)        t.start()        threads.append(t)    for t in threads:        t.join()    print("所有线程执行完毕")    print("总循环次数为:%s" % num)
        • 打印结果:每次运行三个线程,每个线程循环打印10次

          start runstart runstart run00...thread_id=1:name=Thread-1所有线程执行完毕总循环次数为:30
          • 多线程共享资源,可以使用全局变量global

          多线程加锁

          • 对于那些需要每次只允许一个线程操作的数据,可以将其操作放到 acquire 和 release 方法之间

            # -*- coding: utf-8 -*-import timeimport threading# 创建锁对象lock = threading.Lock()num = 0def run(n):    global num    for i in range(10):        # 加锁  为了确保下面代码只能由一个线程从头到尾的执行        # 会阻止多线程的并发执行,所以效率会大大降低        """        lock.acquire()        try:            num = num - n            num = num + n        finally:            # 解锁            lock.release()        """        with lock:            time.sleep(2)            print("start")            num = num + 1            print("==============")if __name__ == '__main__':    t1 = threading.Thread(target=run,args=(6,))    t2 = threading.Thread(target=run,args=(9,))    t1.start()    t2.start()    t1.join()    t2.join()    print("num = %s"%(num))
            • 打印结果是每次只能运行一个线程

              start==============...num = 20

              多线程与队列

              • 我们经常会遇到这样的一个问题,这里有成千上万条数据,每次需要取出其中的一条数据进行处理,那么引入多线程该怎么进行任务分配?

              • 我们可以将数据进行分割然后交给多个线程去跑,可是这并不是一个明智的做法。在这里我们可以使用队列与线程相结合的方式进行任务分配。

              • 队列线程的思想:首先创建一个全局共享的队列,队列中只存在有限个元素,并将所有的数据逐条加入到队列中,并调用队列的join函数进行等待。之后便可以开启若干线程,线程的任务就是不断的从队列中取数据进行处理就可以了。

                import threadingimport timeimport queueq = queue.Queue(10)threadLock = threading.Lock()class myThread(threading.Thread):    def __init__(self, threadID, name):        threading.Thread.__init__(self)        self.threadID = threadID        self.name = name        self.exitFlag = 0    def run(self):        while not self.exitFlag:            threadLock.acquire()            if not q.empty():                id = q.get()                print_time(self.name, id)                threadLock.release()            else:                threadLock.release()def print_time(threadName, id):    print ("%s:%s:%s"%(threadName,time.ctime(time.time()),id))    # pass# 创建3个线程threads = []for i in range(3):    name = "Thread-%d" % i    t = myThread(i, name)    t.start()    threads.append(t)print(threads)# 新增队列数据for i in range(10000):    q_name = "Queue:%d" % i    q.put(q_name)# 等待队列清空while not q.empty():    pass# 也可以join方法,与上同效# q.join()# 通知线程,处理完之后关闭for t in threads:    t.exitFlag = 1# 等待所有线程结束之后才退出for t in threads:    t.join()print("Exiting Main Thread")
                • 这里必须要在判断q.empty()前加上线程锁,因为可能会出现这样的一种情况。

                • 某一时刻,队列中还有一个元素,该元素正在被线程A取出,而与此同时线程B正在判断队列q是否为空,而此时线程B中队列q不为空进入后面的操作,但是待B去取元素时,最后一个元素已经被A取出,造成线程等待,显示出被挂起的状态。

                • 我们也可以通过加入q.get(timeout=10)超时操作来弥补这一问题。

                • 打印的结果

                  [<myThread(Thread-0, started 6568)>, <myThread(Thread-1, started 7724)>, <myThread(Thread-2, started 7796)>]Thread-1:Sat Aug 22 11:36:29 2020:Queue:0Thread-1:Sat Aug 22 11:36:29 2020:Queue:1...Thread-1:Sat Aug 22 11:36:30 2020:Queue:9998Thread-1:Sat Aug 22 11:36:30 2020:Queue:9999Exiting Main Thread

                  ThreadPoolExecutor线程池的使用

                  • 锁依然可以运用到线程池

                  • map的使用,接受一个List的数据,会循环调用

                    from concurrent.futures.thread import ThreadPoolExecutorimport timenum = 0def print_time(data):    global num    num += 1    time.sleep(2)    print("start_%s" % data)    print("============")data = []for i in range(50):    data.append(i)with ThreadPoolExecutor(10) as pool:    result = pool.map(print_time, data)# 等待所有线程执行完毕for i in result:    passprint("循环次数=%s" % num)
                    • 打印结果为:每次启动10个线程,启动了5次

                      ============start_46start_49========================循环次数=50
                      • submit接受list的数据,也可以接受字典

                        from concurrent.futures.thread import ThreadPoolExecutorfrom concurrent.futures import as_completedimport timedef print_time(data):    time.sleep(2)    print("start_%s" % data)    print("============")data = []for i in range(50):    data.append(i)with ThreadPoolExecutor(10) as executor:    future_list = []    for i in range(10):        # future = executor.submit(print_time,data)        future = executor.submit(print_time, {"name": 111, "id": 222})        future_list.append(future)    for res in as_completed(future_list):  # 这个futrure_list是你future对象的列表        print(res.result())

                        作者:望月成三人
                        链接:https://www.jianshu.com/p/74d3119903fc
                        来源:简书
                        本文来源于简书,著作权归作者所有。仅用于学习交流,不进行商业用途,如需引用或转载,请注明原出处。如有侵权,请联系删除。

                        不喜欢不看的原因确定内容质量低不看此公众号
                        (0)

                        相关推荐

                        • python笔记29-队列Queue

                          前言 Python的Queue模块提供一种适用于多线程编程的FIFO实现.它可用于在生产者(producer)和消费者(consumer)之间线程安全(thread-safe)地传递消息或其它数据,因 ...

                        • Python进程与线程知识

                          Python进程与线程知识,Python开发语言现在已经是被大家非常看中的编程语言了,本篇文章给读者们分享一下Python进程与线程知识小结,本篇文章具有一定的参考借鉴价值,感兴趣的小伙伴来了解一下吧 ...

                        • 简单明了的 Python 多线程来了

                          线程和进程   计算机的核心是CPU,它承担了所有的计算任务,就像是一座工厂在时刻运行. 如果工厂的资源有限,一次只能供一个车间来使用,也就是说当一个车间开工时其它车间不能工作,也就是一个CPU一次只 ...

                        • python笔记11-多线程之Condition(条件变量)

                          前言 当小伙伴a在往火锅里面添加鱼丸,这个就是生产者行为:另外一个小伙伴b在吃掉鱼丸就是消费者行为.当火锅里面鱼丸达到一定数量加满后b才能吃,这就是一种条件判断了. 这就是本篇要讲的Condition ...

                        • Python数据结构与算法(9)——优先级队列queue例程

                          https://m.toutiao.com/is/euqcKx5/ 前言 queue库提供了一个适用于多线程编程的先进先出(FIFO)数据结构,可以用来在生产者与消费者线程之间安全地传递消息或其他数据 ...

                        • python多线程 代理池爬取天天基金网、股票数据过程解析

                          简介 提到爬虫,大部分人都会想到使用Scrapy工具,但是仅仅停留在会使用的阶段.为了增加对爬虫机制的理解,我们可以手动实现多线程的爬虫过程,同时,引入IP代理池进行基本的反爬操作. 本次使用天天基金 ...

                        • 高中物理重点知识分类解析“39张图”

                          高中物理重点知识分类解析“39张图”

                        • 理解Python多线程:通过易懂的小例子展开

                          4天前 1 默认启动主线程 一般的,程序默认执行只在一个线程,这个线程称为主线程,例子演示如下: 导入线程相关的模块 threading: import threading threading的类方法 ...

                        • 风水知识:解析阳宅风水的最佳坐向与阴阳八卦!

                          一.阳宅风水坐向与阴阳八卦 "坐"的本质特征是什么呢?所谓坐,就是犹如一个人坐下来一样,人坐下来了,就意味着"不动"且要稳,不动即静也,动为阳静为阴.因此,坐的 ...

                        • python笔记27-lxml.etree解析html

                          前言 之前分享过一个python爬虫beautifulsoup框架可以解析html页面,最近看到lxml框架的语法更简洁,学过xpath定位的,可以立马上手. 使用环境: python 3.6 lxm ...

                        • python接口自动化33-json解析神器jsonpath

                          前言 做接口测试的时候,大部分情况下返回的是json数据,我们需要对返回的json断言. 当返回的数据量比较大,并且嵌套的层级很深的时候,很多小伙伴不会取值,往往在返回结果取值上浪费很多时间,于是就有 ...

                        • python接口自动化39-JMESPath解析json数据

                          前言 前面学了 jsonpath 可以很好的解析 json 数据,提取出我们想要的内容,对于平常的基本工作没太大的问题,但有一点点小遗憾. jsonpath 的 python 库功能并不是很强大,不支 ...

                        • 面粉知识大解析!知道这9条干货,你就赢在起跑线上了!

                          一 为什么要用小麦粉制作面包 因为它利用面粉中所含有的独特的性质,即蛋白质,这些蛋白质的含量都在8%-13%中间,这些蛋白质在搅拌的过程中因为水分的吸收形成面筋,混入空气后,残留在面团当中通过酵母的反 ...

                        • 素描头像嘴部知识全解析,三步骤分分钟掌握画嘴要领

                          嘴是脸部运动范围最大.最富有表情变化的部位 今天我们就来学习关于素描中人物的嘴型是如何画好的 嘴部基本结构 嘴的结构包括上唇.下唇.口裂.嘴角和人中等几部分 上唇:上唇颜色比下唇颜色深一点,注意上唇结 ...