python-Thread创建线程(精简)

概述

本节主要介绍python线程的使用,与对进程的使用类似

线程的生命周期

五种状态:

  • 新建(new): 新创建的线程经过初始化后,进入就绪(Runnable)状态
  • 就绪(Runnable):等待线程调度。调度后进入运行状态
  • 运行(Running):当就绪的线程被调度并获得CPU时,便进入运行状态
  • 阻塞(Blocked):暂停运行,解除阻塞后进入Runnable状态重新等待调度
  • 死亡(Dead):线程方法执行完毕返回或者异常终止

从“运行”进入“阻塞”(Blocked):

  • 同步:线程中获取同步锁,但是资源已经被其他线程锁定时,进入Locked状态,直到该资源可获取(获取的顺序由Lock队列控制)
  • 睡眠:线程运行sleep()或join()方法后,线程进入Sleeping状态。区别在于sleep等待固定的时间,而join是等待子线程执行完。当然join也可以指定一个“超时时间”。从语义上来说,如果两个线程a,b, 在a中调用b.join(),相当于合并(join)成一个线程。最常见的情况是在主线程中join所有的子线程。
  • 等待:线程中执行wait()方法后,线程进入Waiting状态,等待其他线程的通知(notify)。

例子

模拟一个线程 下载2个大文件,一个文件下载后,才能下载另一个文件,速度慢,效率低下

import time
import os

def task():
    # 模拟耗时任务,如:迅雷下载
    for i in range(101):
        print("下载文件1,进度:",i)
        time.sleep(0.5)

def task2():
    # 模拟耗时任务,如:迅雷下载
    for i in range(101):
        print("下载文件2,进度:",i)
        time.sleep(0.5)

print("pid:{},父pid:{}".format(os.getpid(),os.getppid()))

task()
task2()

Thread类使用说明

导入模块

import threading

或者

from threading import Thread

创建对象

语法:

Thread(self, group=None, target=None, name=None,args=(), kwargs=None, *, daemon=None)

参数说明:

  • group:一般不使用
  • target:表示调用对象
  • name:为别名
  • args:表示调用对象的位置参数元组
  • kwargs:表示调用对象的关键字参数字典

常用属性

  • name:当前线程别名,在实例化时通过参数name指定,默认为Thread=N,N为从1开始递增的整数

常用方法

  • start():启动线程实例

  • is_alive():判断线程实例是否还在执行,返回布尔值

  • join([timeout]):参见

  • run():参见 python-Thread子类创建进程

threading模块使用说明

  • threading.current_thread():返回当前线程对象
  • threading.main_thread():返回主线程对象
  • threading.enumerate():返回当前存在的所有线程对象的列表
  • threading.active_count(): 返回当前存活的线程对象的数量。通过计算len(threading.enumerate())长度而来

例子:多线程同时下载文件


import time
import os
import threading

def task():
    # 模拟耗时任务,如:迅雷下载
    for i in range(101):
        print("线程:",threading.current_thread().name,",下载文件1,进度:",i)
        time.sleep(0.5)

def task2():
    # 模拟耗时任务,如:迅雷下载
    for i in range(101):
        print("线程:",threading.current_thread().name,"下载文件2,进度:",i)
        time.sleep(0.5)

print("pid:{},父pid:{}".format(os.getpid(),os.getppid()))

# 创建线程,执行task()函数,注意:后面不要加小括号(),表示调用
t1 = threading.Thread(target=task)
# 启动线程
t1.start()

# 创建线程,执行task()函数,注意:后面不要加小括号(),表示调用
t2 = threading.Thread(target=task2)
# 启动线程
t2.start()

例子:共享变量

为了提高速度,启动2个线程,下载同一个文件,第一个线程从0开始下载,第二个线程从51开始下载

而且修改总进度

import time
import os
import threading

# 全局变量,多线程共享变量
count = 0

def task():
    global count
    # 模拟耗时任务,如:迅雷下载
    for i in range(51):
        print(threading.current_thread().name+"--下载文件1,进度:" ,i)
        count += 1
        # 在函数中访问全局变量
        print("总进度:",count)
        time.sleep(0.2)

def task2():
    global count
    # 模拟耗时任务,如:迅雷下载
    for i in range(51,101):
        print(threading.current_thread().name+"--下载文件1,进度:" ,i)
        count += 1
        # 在函数中访问全局变量
        print("总进度:", count)
        time.sleep(0.2)


print("pid:{},父pid:{}".format(os.getpid() ,os.getppid()))
# 让子线程执行task()函数
t1 = threading.Thread(target=task)
# 调用函数
t1.start()

# 让子线程执行task2()函数
t1 = threading.Thread(target=task2)
# 调用函数
t1.start()

原文出处:/show_1IX5dPpvy2kU.html