python多线程:Thread类的用法

我们要创建Thread对象,然后让他们运行,每个Thread对象代表一个线程,在每个线程中我们可以让程序处理不同的任务,这就是多线程编程。

创建Thread对象有两种方法:
1.直接创建Thread,将一个callable对象从类的构造器传递出去,这个callable就是回调函数,用来处理任务。
2.编写一个自定义类继承Thread,然后复写run()方法,在ru()方法中编写任务处理代码,然后创建Thread的子类。

1.直接创建Thread对象

# 导入Python标准库中的Thread模块 
from threading import Thread 
# 创建一个线程 
mthread = threading.Thread(target=function_name, args=(function_parameter1, function_parameterN)) 
# 启动刚刚创建的线程 
mthread .start()

参数说明:
function_name: 需要线程去执行的方法名
args: 线程执行方法接收的参数,该属性是一个元组,如果只有一个参数也需要在末尾加逗号。
1)创建多线程
Thread的构造方法中,最重要的参数是target,所以我们需要将一个callable对象赋值给它,线程才能正常运行。
如果要让一个Thread对象启动,调用它的start()方法即可。

import threading
import time
def test():
    for i in range(5):
        print('The {} child thile '.format(i))
        time.sleep(1)
thread = threading.Thread(target=test)
thread.start()
# thread.join()

for i in range(5):
    print('The {} main thile '.format(i))
    time.sleep(1)


上面代码很简单,在主线程上打印 5 次,在一个子线程上打印 5 次。


The 0 child thile The 0 main thile 

The 1 child thile The 1 main thile 

The 2 child thile 
The 2 main thile 
The 3 main thile The 3 child thile 

The 4 child thile 
The 4 main thile 

上面的 callable 没有参数,如果需要传递参数的话,args 是固定参数,kwargs 是可变参数。

2)Thread的名字

每一个Thread都有一个name的属性,代表的就是线程的名字,这个可以在构造方法中赋值。如果在构造方法中没有为name赋值的话,默认就是“Thread-N”的形式,N是数字。

import threading
import time
def test():
    for i in range(5):
        print(threading.current_thread().name+" test ",i)
        time.sleep(1)
thread=threading.Thread(target=test)
thread.start()
for i in range(5):
    print("This is "+threading.current_thread().name+"main ",i)
    time.sleep(1)

输出为:

Thread-1 test This is MainThreadmain   00

Thread-1 test  1
This is MainThreadmain  1
Thread-1 test  2
This is MainThreadmain  2
This is MainThreadmain  3Thread-1 test 
 3
Thread-1 test  4
This is MainThreadmain  4

在Thread对象创建时,给name赋值

thread = threading.Thread(target=test,name='aoligei')

运行结果为:

aoligei test This is MainThreadmain   00

This is MainThreadmain  1
aoligei test  1
This is MainThreadmain  2
aoligei test  2
This is MainThreadmain  3
aoligei test  3
This is MainThreadmain  4
aoligei test  4

3)Thread的生命周期

1.创建对象时,代表Thread内部被初始化
2.调用start()方法后,thread会开始运行
3.thread代码正常运行结束或者遇到异常,线程会终止。
可以通过Thread的is_alive()方法查询线程是否还在运行。is_alive() 返回 True 的情况是 Thread 对象被正常初始化,start() 方法被调用,然后线程的代码还在正常运行。

import threading
import time
def test():
    for i in range(5):
        print(threading.current_thread().name+' test ',i,"*"*10)
        time.sleep(0.5)

thread = threading.Thread(target=test,name='aoligei')
thread.start()

for i in range(5):
    print(threading.current_thread().name+' main ', i)
    print(thread.name+' is alive ', thread.is_alive())
    time.sleep(1)

设置子线程的睡眠时间更短,可以让它早点结束

aoligei test MainThread main   00
 aoligei is alive ********** 
True
aoligei test  1 **********
MainThread main  1
aoligei is alive  True
aoligei test  2 **********
aoligei test  3 **********
MainThread main  2
aoligei is alive  True
aoligei test  4 **********
MainThread main  3
aoligei is alive  False
MainThread main  4
aoligei is alive  False

4)join()方法提供阻塞手段

import threading
import time
def test():
    for i in range(5):
        print(threading.current_thread().name+' test ',i,"*"*10)
        time.sleep(2)

thread = threading.Thread(target=test,name='aoligei')
thread.start()
thread.join()
for i in range(5):
    print(threading.current_thread().name+' main ', i)
    print(thread.name+' is alive ', thread.is_alive())
    time.sleep(1)

调用一个 Thread 的 join() 方法,可以阻塞自身所在的线程。主线程创建了 aoligei 对象后,让其 start,然后通过调用 join() 方法,实现等待。程序运行结果如下:

aoligei test  0 **********
aoligei test  1 **********
aoligei test  2 **********
aoligei test  3 **********
aoligei test  4 **********
MainThread main  0
aoligei is alive  False
MainThread main  1
aoligei is alive  False
MainThread main  2
aoligei is alive  False
MainThread main  3
aoligei is alive  False
MainThread main  4
aoligei is alive  False

默认情况下,join()会一直等待对应线程的结束,但可以通过参数赋值,等待规定的时间即可。

def join(self.timeout=None):

timeout是一个浮点参数,单位是秒。

5)守护线程

import threading
import time
def test():
    for i in range(5):
        print(threading.current_thread().name+' test ',i,"*"*10)
        time.sleep(2)

thread = threading.Thread(target=test,name='aoligei')
thread.start()

for i in range(5):
    print(threading.current_thread().name+' main ', i)
    print(thread.name+' is alive ', thread.is_alive())
    time.sleep(1)

输出为:

aoligei test MainThread main   00 
**********aoligei is alive 
 True
MainThread main  1
aoligei is alive  True
aoligei test  1 **********
MainThread main  2
aoligei is alive  True
MainThread main  3
aoligei is alive  True
aoligei test  2 **********
MainThread main  4
aoligei is alive  True
aoligei test  3 **********
aoligei test  4 **********

MainThread结束运行后,aoligei仍然在运行,这是因为MainThread在等待其他线程的结束。
aoligei的daemon属性默认为False,这使得 MainThread 需要等待它的结束,自身才结束。
如果要达到守护线程(MainThread 结束,子线程也立马结束),怎么做呢? 其实很简单,只需要在子线程调用 start() 方法之前设置 daemon 就好了。 当然也可以在子线程的构造器中传递 daemon 的值为 True。

thread = threading.Thread(target=test,name='TestThread',daemon=True)
# thread.setDaemon(True)

修改之后运行结果为:

aoligei test MainThread main   00 
aoligei is alive ********** 
True
MainThread main  1
aoligei is alive  True
aoligei test  1 **********
MainThread main  2
aoligei is alive  True
MainThread main  3
aoligei is alive  True
aoligei test  2 **********
MainThread main  4
aoligei is alive  True

6)线程数量
threading.enumerate():返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。

def enumerate():
“”"Return a list of all Thread objects currently alive.
The list includes daemonic threads, dummy thread objects created by current_thread(), and the main thread. It excludes terminated threads and threads that have not yet been started.

import threading
import time
def func1():
    print("This is func1")
    time.sleep(1)
def func2():
    print("This is func2")
    time.sleep(1)

for i in range(4):
    t1=threading.Thread(target=func1)
    t2 = threading.Thread(target=func2)
    t2.start()
    t1.start()
    le=len(threading.enumerate())
    print("当前线程数为",le)

运行结果为:

This is func2
This is func1当前线程数为
 3
This is func2
This is func1当前线程数为
 5
This is func2
This is func1当前线程数为
 7
This is func2
This is func1当前线程数为
 9

7)其他的方法

Thread类的其他方法
getName():返回线程名
setName(): 设置线程名

threading模块提供的方法
threading.currentThread():返回当前的线程变量。
threading.activeCount():返回正在运行的线程数量,与len(threading.enumerate()) 有相同的结果

2.自定义类继承Thread

自定义一个Thread的子类,然后复写它的run()方法

import threading
import time
class TestThread(threading.Thread):
    def __init__(self,name=None):
        threading.Thread.__init__(self,name=name)
    def run(self):
        for i in range(5):
            print(threading.current_thread().name+" test ",i)
            time.sleep(1)
thread=TestThread(name='aoligei')
thread.start()

for i in range(5):
    print(threading.current_thread().name+" main ",i)
    time.sleep(1)

自定义了 TestThread 这个类,然后继承threading.Thread 只有在 run() 方法中处理逻辑,最终运行结果如下:

aoligei test MainThread main   00

aoligei test MainThread main   1
1
MainThread main  2
aoligei test  2
aoligei test  3
MainThread main  3
MainThread main  4
aoligei test  4

参考链接:Python多线程编程(一)

猜你喜欢

转载自blog.csdn.net/liulanba/article/details/114434926