沙滩星空的博客沙滩星空的博客

python多线程线程threading.Thread()

先看示例代码:

from flask import Flask
import webbrowser
import threading
import time

app = Flask(__name__)

def open_web_server():
    app.run(port=8080)

def open_url():
    time.sleep(1)
    webbrowser.open('http://127.0.0.1:8080')

class myThread (threading.Thread):
    def __init__(self, thread_id, name, func):
        threading.Thread.__init__(self)
        self.thread_id = thread_id
        self.name = name
        self.func = func

    def run(self):
        print("开始线程:" + self.name)
        self.func()
        print("退出线程:" + self.name)

if __name__ == '__main__':
    t1 = myThread(1, 't1', open_web_server)
    t2 = myThread(2, 't2', open_url)
    t1.start()
    t2.start()

以下代码,在1秒内,一次性打印了5条输出

import threading
import time

def saySorry():
  print("亲爱的,我错了,我能吃饭了吗?")
  time.sleep(1)

if __name__ == "__main__":
  for i in range(5):
    t = threading.Thread(target=saySorry)
    t.start() #启动线程,即让线程开始执行

可看出使用多线程并发操作,花费时间要短很多

当调用 start() 时,才会真正的创建线程,并且开始执行

每个线程都有一个唯一标示符,来区分线程中的主次关系

主线程:mainThread,Main函数或者程序主入口,都可以称为主线程

子线程:Thread-x 使用 threading.Thread() 创建出来的都是子线程

线程数量:主线程数 + 子线程数

import threading
from time import sleep,ctime

def sing():
  for i in range(3):
    print("正在唱歌...%d"%i)
    sleep(1)

def dance():
  for i in range(3):
    print("正在跳舞...%d"%i)
    sleep(1)

if __name__ == '__main__':
  print('---开始---:%s'%ctime())

  t1 = threading.Thread(target=sing)
  t2 = threading.Thread(target=dance)

  t1.start()
  t2.start()

  while True:
    length = len(threading.enumerate())
    print('当前运行的线程数为:%d'%length)
    if length<=1:
      break

    sleep(0.5)

输出如下:

---开始---:Fri Feb 19 04:52:08 2021
正在唱歌...0
正在跳舞...0
当前运行的线程数为:3
当前运行的线程数为:3
正在跳舞...1
正在唱歌...1
当前运行的线程数为:3
当前运行的线程数为:3
正在跳舞...2
正在唱歌...2
当前运行的线程数为:3
当前运行的线程数为:3
当前运行的线程数为:2
当前运行的线程数为:1

主线程结束前,会等待所有的子线程结束,才会终止线程

传递参数的方法:

使用 args, kwargs 传递参数

threading.Thread(target=sing, args=(10, 100, 100))
threading.Thread(target=sing, kwargs={"a": 10, "b":100, "c": 100})
threading.Thread(target=sing, args=(10, ), kwargs={"b": 10, "c": 100})

线程的执行顺序

上面的代码中只能保证每个线程都运行完整个run函数,但是线程的启动顺序、run函数中每次循环的执行顺序都不能确定。

守护线程

如果在程序中将子线程设置为守护线程,则该子线程会在主线程结束时自动退出.设置方式为thread.setDaemon(True),要在thread.start()之前设置. 默认False,也就是主线程结束时,子线程依然在执行。

import threading
import time

def test():
  for i in range(10):
    print("test is run:", i)
    time.sleep(1)

if __name__ == '__main__':
  # 创建子线程
  t1 = threading.Thread(target=test)
  # 设置为守护线程。主线程结束后,守护的子线程也跟着结束
  # t1.setDaemon(True)
  # 启动子线程
  t1.start()
  # 休眠2秒
  time.sleep(2)
  print("我 OVER 了")
  # 退出
  exit()

不开启守护进程

test is run: 0
test is run: 1
我 OVER 了
test is run: 2
......
test is run: 9

开启守护进程

test is run: 0
test is run: 1
我 OVER 了

经测试,开启多个子线程,包含守护线程和非守护线程,则以守护线程无效。

def test1():
    for i in range(9):
        print("test1 is run:", i)
        time.sleep(1)

def test2():
    for i in range(9):
        print("test2 is run:", i)
        time.sleep(1)

if __name__ == '__main__':
    # 创建子线程
    t1 = threading.Thread(target=test1)
    t2 = threading.Thread(target=test2)
    # 设置为守护线程。主线程结束后,守护的子线程也跟着结束
    t1.setDaemon(True)
    # 启动子线程
    t1.start()
    t2.start()
    # 休眠2秒
    time.sleep(3)
    print("我 OVER 了")
    # 退出
    exit()

输出如下:

test1 is run: 0
test2 is run: 0
test1 is run: 1
test2 is run: 1
test1 is run: 2
test2 is run: 2
我 OVER 了
test1 is run: 3
test2 is run: 3
....
test1 is run: 8
test2 is run: 8

阻塞主线程join(timeout)
thread.join(): 如果想让主线程等待子线程结束后再运行的话,就需要用到join(),此方法是在start() 之后


threading --- 基于线程的并行 https://docs.python.org/zh-cn/3/library/threading.html
python中的线程threading.Thread()使用详解 https://www.jb51.net/article/176573.htm

Python多线程的原理与实现 https://blog.csdn.net/daiyu__zz/article/details/81912018

未经允许不得转载:沙滩星空的博客 » python多线程线程threading.Thread()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址