我们要创建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多线程编程(一)