• 技术文章 >后端开发 >Python教程

    带你一起解读Python多线程

    长期闲置长期闲置2022-03-02 17:35:48转载86
    本篇文章给大家带来了关于python的相关知识,其中主要介绍了关于多线程的相关知识,多线程类似于同时执行多个不同的程序,有很多的优点,下面我们就来看一下,希望对大家有帮助。

    推荐学习:python教程

    线程讲解

      多线程类似于同时执行多个不同程序,多线程运行有如下优点:

      线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
      每个线程都有他自己的一组CPU寄存器,称为线程的上下文,该上下文反映了线程上次运行该线程的CPU寄存器的状态。
      指令指针堆栈指针寄存器是线程上下文中两个最重要的寄存器,线程总是在进程的上下文中运行的,这些地址都用于标志拥有线程的进程地址空间中的内存。
      线程可以被抢占(中断)。
      在其他线程正在运行时,线程可以暂时搁置(也称为睡眠) – 这就是线程的退让。
      线程可以分为:

      Python3 线程中常用的两个模块为:

      thread 模块已被废弃。用户可以使用 threading 模块代替。所以,在 Python3 中不能再使用"thread" 模块。为了兼容性,Python3 将 thread 重命名为 “_thread”。

    开始学习Python线程

      Python中使用线程有两种方式:函数或者用类来包装线程对象。
      函数式:调用 _thread 模块中的start_new_thread()函数来产生新线程。语法如下:

    _thread.start_new_thread ( function, args[, kwargs] )

      参数说明:

      实例:

    #!/usr/bin/python3
    
    import _thread
    import time
    
    # 为线程定义一个函数
    def print_time( threadName, delay):
        count = 0
        while count < 5:
            time.sleep(delay)
            count += 1
            print ("%s: %s" % ( threadName, time.ctime(time.time()) ))
    
    # 创建两个线程
    try:
        _thread.start_new_thread( print_time, ("Thread-1", 2, ) )
        _thread.start_new_thread( print_time, ("Thread-2", 4, ) )
    except:
        print ("Error: 无法启动线程")
    
    while 1:
        pass

      执行以上程序输出结果如下:
    这里写图片描述

    线程模块

      Python3 通过两个标准库 _thread 和 threading 提供对线程的支持。

      除了使用方法外,线程模块同样提供了Thread类来处理线程,Thread类提供了以下方法:

    使用 threading 模块创建线程

      我们可以通过直接从 threading.Thread 继承创建一个新的子类,并实例化后调用 start() 方法启动新线程,即它调用了线程的 run() 方法:

    #!/usr/bin/python3
    
    import threading
    import time
    
    exitFlag = 0
    
    class myThread (threading.Thread):
        def __init__(self, threadID, name, counter):
            threading.Thread.__init__(self)
            self.threadID = threadID
            self.name = name
            self.counter = counter
        def run(self):
            print ("开始线程:" + self.name)
            print_time(self.name, self.counter, 5)
            print ("退出线程:" + self.name)
    
    def print_time(threadName, delay, counter):
        while counter:
            if exitFlag:
                threadName.exit()
            time.sleep(delay)
            print ("%s: %s" % (threadName, time.ctime(time.time())))
            counter -= 1
    
    # 创建新线程
    thread1 = myThread(1, "Thread-1", 1)
    thread2 = myThread(2, "Thread-2", 2)
    
    # 开启新线程
    thread1.start()
    thread2.start()
    thread1.join()
    thread2.join()
    print ("退出主线程")

      以上程序执行结果如下:
    这里写图片描述

    线程同步

      如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。
      使用 Thread 对象的 Lock 和 Rlock 可以实现简单的线程同步,这两个对象都有 acquire 方法和 release 方法,对于那些需要每次只允许一个线程操作的数据,可以将其操作放到 acquire 和 release 方法之间。如下:
      多线程的优势在于可以同时运行多个任务(至少感觉起来是这样)。但是当线程需要共享数据时,可能存在数据不同步的问题。
      考虑这样一种情况:一个列表里所有元素都是0,线程"set"从后向前把所有元素改成1,而线程"print"负责从前往后读取列表并打印。
      那么,可能线程"set"开始改的时候,线程"print"便来打印列表了,输出就成了一半0一半1,这就是数据的不同步。为了避免这种情况,引入了锁的概念。
      锁有两种状态——锁定和未锁定。每当一个线程比如"set"要访问共享数据时,必须先获得锁定;如果已经有别的线程比如"print"获得锁定了,那么就让线程"set"暂停,也就是同步阻塞;等到线程"print"访问完毕,释放锁以后,再让线程"set"继续。
      经过这样的处理,打印列表时要么全部输出0,要么全部输出1,不会再出现一半0一半1的尴尬场面。
      实例:

    #!/usr/bin/python3
    
    import threading
    import time
    
    class myThread (threading.Thread):
        def __init__(self, threadID, name, counter):
            threading.Thread.__init__(self)
            self.threadID = threadID
            self.name = name
            self.counter = counter
        def run(self):
            print ("开启线程: " + self.name)
            # 获取锁,用于线程同步
            threadLock.acquire()
            print_time(self.name, self.counter, 3)
            # 释放锁,开启下一个线程
            threadLock.release()
    
    def print_time(threadName, delay, counter):
        while counter:
            time.sleep(delay)
            print ("%s: %s" % (threadName, time.ctime(time.time())))
            counter -= 1
    
    threadLock = threading.Lock()
    threads = []
    
    # 创建新线程
    thread1 = myThread(1, "Thread-1", 1)
    thread2 = myThread(2, "Thread-2", 2)
    
    # 开启新线程
    thread1.start()
    thread2.start()
    
    # 添加线程到线程列表
    threads.append(thread1)
    threads.append(thread2)
    
    # 等待所有线程完成
    for t in threads:
        t.join()
    print ("退出主线程")

      执行以上程序,输出结果为:
    这里写图片描述

    线程优先级队列(Queue)

      Python 的 Queue 模块中提供了同步的、线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列LifoQueue,和优先级队列 PriorityQueue。
      这些队列都实现了锁原语,能够在多线程中直接使用,可以使用队列来实现线程间的同步。
      Queue 模块中的常用方法:

      实例:

    #!/usr/bin/python3
    
    import queue
    import threading
    import time
    
    exitFlag = 0
    
    class myThread (threading.Thread):
        def __init__(self, threadID, name, q):
            threading.Thread.__init__(self)
            self.threadID = threadID
            self.name = name
            self.q = q
        def run(self):
            print ("开启线程:" + self.name)
            process_data(self.name, self.q)
            print ("退出线程:" + self.name)
    
    def process_data(threadName, q):
        while not exitFlag:
            queueLock.acquire()
            if not workQueue.empty():
                data = q.get()
                queueLock.release()
                print ("%s processing %s" % (threadName, data))
            else:
                queueLock.release()
            time.sleep(1)
    
    threadList = ["Thread-1", "Thread-2", "Thread-3"]
    nameList = ["One", "Two", "Three", "Four", "Five"]
    queueLock = threading.Lock()
    workQueue = queue.Queue(10)
    threads = []
    threadID = 1
    
    # 创建新线程
    for tName in threadList:
        thread = myThread(threadID, tName, workQueue)
        thread.start()
        threads.append(thread)
        threadID += 1
    
    # 填充队列
    queueLock.acquire()
    for word in nameList:
        workQueue.put(word)
    queueLock.release()
    
    # 等待队列清空
    while not workQueue.empty():
        pass
    
    # 通知线程是时候退出
    exitFlag = 1
    
    # 等待所有线程完成
    for t in threads:
        t.join()
    print ("退出主线程")

      以上程序执行结果:
    这里写图片描述

    推荐学习:python学习教程

    以上就是带你一起解读Python多线程的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:CSDN,如有侵犯,请联系admin@php.cn删除
    专题推荐:Python
    上一篇:Python学习之解析Flask运行原理(图文详解) 下一篇:一起来分析Python函数式编程
    PHP编程就业班

    相关文章推荐

    • 浅析Python中怎么用Redis• php和python是什么意思• linux怎么查询python版本• PHP 正在干掉 Python !• 分享10个有趣且实用的Python模块,看看他们的功能吧!

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网