python从入门到精通(十九):python的多线程详细使用

python的多线程详细使用

  • 1.什么是线程
  • 2.线程的作用
  • 3.导入线程
    • 4.创建线程
      • 启动线程
      • 线程阻塞
      • 线程的方法
    • 守护线程
    • 线程阻塞
      • 2个都是守护线程
      • 1个是守护线程
    • 线程间通信

1.什么是线程

线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

2.线程的作用

Python中的程序默认是只有一个主线程的,也就是说,执行程序的时候,你写的代码都是串行执行的,CPU利用率可能并没有得到很好的利用,还有很多的空闲,而这个时候利用多线程,多线程是指同时使用多个线程执行代码,以实现并发执行任务的目的,CPU利用率将会大大提升,程序速度也就能大大增快

3.导入线程

多线程开发推荐使用 threading 模块

from threading import Thread

4.创建线程

调用threading.Thread类

threading.Thread(target=None, name=None, args=(), kwargs={})
# target 指要创建的线程的方法名,name 指给此线程命名,命名后可以调用 threading.current_thread().name 方法输出该线程的名字
# args/kwargs 指 target 指向的方法需要传递的参数,必须是元组形式,如果只有一个参数,需要以添加逗号

实例化线程

# method 为线程要执行的具体方法
thread01 = Thread(target=method)  #method要使用线程的函数名称

实现两条线程

thread02 = Thread(target=method)

实现多个线程依次类推

启动线程

thread01.start()
thread01.start()

线程阻塞

等待所有线程执行完成再进行下一步操作

thread01.join()
thread02.join()
# 等待线程执行完成

线程的方法

方法 描述
threading.current_thread() 返回当前线程的信息
threading.enumerate() 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程
threading.active_count() 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果
import time
import threading
from threading import Thread
def task():
    num = 0
    for i in range(100):
        num *= i
        result.append(num)
   

thread01 = Thread(target=task)
thread02 = Thread(target=task)
if __name__ == "__main__":
    thread01.start()
    thread02.start()
    print("正在运行的线程数量", threading.active_count())
    print("将当前所有线程的具体信息展示出来", threading.enumerate())
    print("返回当前线程的信息", threading.current_thread())

 2
将当前所有线程的具体信息展示出来 [<_MainThread(MainThread, started 12752)>]
返回当前线程的信息 <_MainThread(MainThread, started 12752)>

守护线程

Python在进程启动起来后,会自动创建一个主线程,主线程默认会等待所有线程执行完成之后再退出,但是如果我们设置了守护线程,主线程任务一旦完成,所有子线程将会和主线程一起结束,即使子线程没有执行完也会退出。

方法一:设置守护线程是创建子线程对象时,以daemon参数的形式指定

thread01 = Thread(target=task,name="t1",daemon=True)

方法二:通过setDaemon(True)的形式进行设置

thread01.setDaemon(True)
在这里插入代码片

线程阻塞

假如说我们不希望主线程完成直接退出而不等待其他线程的话,我们可以为主线程设置阻塞,并设计好阻塞时间,以等待其他线程执行完毕。用join()方法使主线程陷入阻塞,是实现线程同步的一种方式。参数timeout可以用来设置主线程陷入阻塞的时间,

2个都是守护线程

def task(num):
    print('线程名称:', threading.current_thread().name, '参数:', num, '开始时间:',
          time.strftime('%Y-%m-%d %H:%M:%S'))

thread01 = Thread(target=task, name="t1", daemon=True, args=(6,))
thread02 = Thread(target=task, name="t2", daemon=True, args=(10,))
if __name__ == "__main__":
    print('主线程开始时间:', time.strftime('%Y-%m-%d %H:%M:%S'))
    thread01.start()
    thread02.start()
    thread01.join(timeout=3)  # 主线程等待3秒 等待线程1执行完
    thread02.join(timeout=3)  # 主线程阻塞3秒 等待线程2执行完 共阻塞6秒 全部执行完毕
    print("正在运行的线程数量", threading.active_count())
    print("将当前所有线程的具体信息展示出来", threading.enumerate())
    print("返回当前线程的信息", threading.current_thread())

1个是守护线程

一个子线程设为非守护线程,另一个子线程设为守护线程,主线程等待3秒后结束,看看输出的情况。

def task(num):
    for i in range(num):
        print('线程名称:', threading.current_thread().name, '参数:', num, '开始时间:',
              time.strftime('%Y-%m-%d %H:%M:%S'))
        time.sleep(2)


thread01 = Thread(target=task, name="t1",daemon=True, args=(1,))

thread02 = Thread(target=task, name="t2",args=(100,))
if __name__ == "__main__":
    print('主线程开始时间:', time.strftime('%Y-%m-%d %H:%M:%S'))
    thread01.start()
    thread02.start()
    # 主线程等待3秒
    time.sleep(3)
    print('{} Runing'.format(threading.current_thread().name))
    print("正在运行的线程数量", threading.active_count())
    print("将当前所有线程的具体信息展示出来", threading.enumerate())
    print("返回当前线程的信息", threading.current_thread())
主线程开始时间: 2024-02-12 16:07:05
线程名称: t1 参数: 1 开始时间: 2024-02-12 16:07:05
线程名称: t2 参数: 100 开始时间: 2024-02-12 16:07:05
线程名称: t2 参数: 100 开始时间: 2024-02-12 16:07:07
MainThread Runing
正在运行的线程数量 2
将当前所有线程的具体信息展示出来 [<_MainThread(MainThread, started 9624)>, <Thread(t2, started 7112)>]
返回当前线程的信息 <_MainThread(MainThread, started 9624)>
线程名称: t2 参数: 100 开始时间: 2024-02-12 16:07:09
线程名称: t2 参数: 100 开始时间: 2024-02-12 16:07:11
线程名称: t2 参数: 100 开始时间: 2024-02-12 16:07:13

守护进程已经执行完了,但是非守护进程还在执行,程序也就还在执行,一旦非守护进程结束,会随主线程全部结束。

线程间通信

线程之间共享同一块内存。子线程虽然可以通过指定target来执行一个函数,但是这个函数的返回值是没有办法直接传回主线程的。我们使用多线程一般是用于并行执行一些其他任务,因此获取子线程的执行结果十分有必要。

你可能感兴趣的:(python,python,pycharm)