Python3 threading模块创建线程

Posted 胜天半月子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python3 threading模块创建线程相关的知识,希望对你有一定的参考价值。

文章目录


前言

threading 模块除了包含 _thread 模块中的所有方法外,还提供的其他方法:

  • threading.currentThread(): 返回当前的线程变量。
  • threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
  • threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。

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

  • run(): 用以表示线程活动的方法。
  • start():启动线程活动。
  • join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。
  • isAlive(): 返回线程是否活动的。
  • getName(): 返回线程名。
  • setName(): 设置线程名。
  • 参考文章
  1. python3并发编程(多进程,多线程,多任务) ⭐⭐建议先阅读本篇文章

一、使用 threading 模块创建线程

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

  • 步骤
  1. 创建类,继承自threading.Thread类
  2. 实例化创建的线程类
  3. 调用start()方法 [会自动调用run()方法]
  • 代码如下(示例一):
import threading
import time

exitFlag = 0

# 创建类  继承自threading.Thread类
class myThread (threading.Thread):
    # 注意:不要忘记在子类中初始化父类的方法Thread.__init__(self) 。需要重构 run() 方法来执行多线程的程序。
    def __init__(self, threadID, name, delay): 
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.delay = delay
        
    def run(self):
        print ("开始线程:" + self.name)
        print_time(self.name, self.delay, 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 ("退出主线程")

join()方法只有在你需要等待线程完成然后在做其他事情的时候才是有用的。本例中是主线程等待子线程thread1,thread2运行完毕后再执行print (“退出主线程”)语句。

  • 运行结果
  • 注意:不要忘记在子类中初始化父类的方法Thread.init(self) 。需要重构 run() 方法来执行多线程的程序。
  • 代码如下(示例二):

若将print (“退出主线程”)语句放在join()语句之前,相当于join()语句是没有任何作用的

...
...
...
print ("退出主线程")
thread1.join()
thread2.join()


通过这次实验也不难发现主线程的运行速度是非常快的,优于子线程率先执行结束!

  • 代码如下(示例三):

若注释掉其中的一个join()语句,又会发生什么情况呢?

...
...
...
thread1.join()
# thread2.join()

print ("退出主线程")


上述结果表明,主线程不需要等待子线程2结束后再输出print()语句,只需要等待子线程1结束后直接输出print()语句。即不管子线程2的状态如何,只要子线程1结束,主线程就输出print()语句。


二、资源独占

  • 案例一
"""
多线程 资源独占
    1、程序中有主线程、子线程,但是多个线程的执行过程,没有顺序。
        那个执行可以执行由CPU管理的!

    2、子线程没有执行结束时,主线程不会退出
       子线程没有执行结束时,主线程中的代码可以全部执行。
       一直到所有的子线程全部运行完毕,主线程才能退出[当前程序]

    3、线程资源独占:强制独占-当前时刻已经启动的线程占用所有资源
        其他线程排队,提升部分线程的优先级,将并发执行变成同步执行
"""
import time
import threading


def test(num):
    """计数器"""
    for i in range(num):
        print(f"threading.current_thread().getName()当前的循环次"
              f"数:i+1;存活线程:threading.active_count()")
        time.sleep(1)


if __name__ == "__main__":
    """程序启动的入口"""
    # 创建两个线程
    t1 = threading.Thread(target=test, args=(5,))
    t2 = threading.Thread(target=test, args=(3,))

    # 启动线程
    t1.start()
    t1.join() # ? 位置:t1占用所有资源,线程运行完毕后,其他线程才能执行。
    # t2.join() # 位置:t2线程没有启动,抢占资源就会报错!
    t2.start()
    # t1.join()   # ? 位置:t1线程t2线程,分配所有资源,等待t1线程和t2线程运行完成后,其他线程才能执行
    # t2.join()  # 如果已经由t1.join()在上一行编写了,这里就没有必要写t2.join()

    # 主线程中:会不会等待t1和t2执行完成后,再执行?
    for i in range(2):
        print(f"threading.current_thread().getName() i:i")
        time.sleep(1)
    print("main线程执行完成......")
  • 运行结果

  • 案例二

...
...
...
    # 启动线程
    t1.start()
    t1.join() # ? 位置:t1占用所有资源,线程运行完毕后,其他线程才能执行。
    t2.join() # 位置:t2线程没有启动,抢占资源就会报错!
    t2.start()
    # t1.join()   # ? 位置:t1线程t2线程,分配所有资源,等待t1线程和t2线程运行完成后,其他线程才能执行
    # t2.join()  # 如果已经由t1.join()在上一行编写了,这里就没有必要写t2.join()

...
  • 运行结果
  • 案例三
...
...
...
    # 启动线程
    t1.start()
    # t1.join() # ? 位置:t1占用所有资源,线程运行完毕后,其他线程才能执行。
    # t2.join() # 位置:t2线程没有启动,抢占资源就会报错!
    t2.start()
    t1.join()   # ? 位置:t1线程t2线程,分配所有资源,等待t1线程和t2线程运行完成后,其他线程才能执行
    # t2.join()  # 如果已经由t1.join()在上一行编写了,这里就没有必要写t2.join()
...
  • 运行结果
  • 案例四
...
...
...
    # 启动线程
    t1.start()
    # t1.join() # ? 位置:t1占用所有资源,线程运行完毕后,其他线程才能执行。
    # t2.join() # 位置:t2线程没有启动,抢占资源就会报错!
    t2.start()
    # t1.join()   # ? 位置:t1线程t2线程,分配所有资源,等待t1线程和t2线程运行完成后,其他线程才能执行
    t2.join()  # 如果已经由t1.join()在上一行编写了,这里就没有必要写t2.join()
...


以上是关于Python3 threading模块创建线程的主要内容,如果未能解决你的问题,请参考以下文章

Python3 threading模块创建线程

Python3 -- 多线程(threading模块queue模块)

python多线程编程

Python3多线程_thread模块的应用

Python3多线程_thread模块的应用

Python3多线程_thread模块的应用