一、概述
运行一个程序时,默认会启动一个主线程,控制程序的运行,也成为控制线程或主线程。除了主线程之外,还可以新建子线程来处理程序,这就是多线程。多线程可以同时处理多个任务,提高效率,特别时IO操作比较多的时候。
二、多线程模块介绍
多线程模块_thread和threading。_thread 提供了低级别的、原始的线程以及一个简单的锁,它相比于 threading 模块的功能还是比较有限的。threading是高级模块,对_thread进行了封装。绝大多数情况下,使用threading这个高级模块。
三、threading模块
threading模块提供的类:
Thread, Lock, Rlock, Condition, [Bounded]Semaphore, Event, Timer, local。
threading模块提供的常用方法:
threading.currentThread(): 返回当前的线程变量。
threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
threading 模块提供的常量:
threading.TIMEOUT_MAX 设置threading全局超时时间。
四、开启线程的两种方式
有函数和类两种方式创建多线程。
函数方式
启动一个线程就是把一个函数传入并创建Thread实例,然后调用start()开始执行。
Thread构造函数
Thread(group=None, target=None, name=None, args=(), kwargs={})
group: 线程组,目前还没有实现,库引用中提示必须是None;
target: 要执行的方法;
name: 线程名;
args/kwargs: 要传入方法的参数。
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
import threading
import time
def run(sec):
print('%s 线程开始了!' %threading.current_thread().name)
time.sleep(sec)
print('%s 线程结束了!' %threading.current_thread().name)
if __name__ == '__main__':
print('主线程开始执行:', threading.current_thread().name)
s_time = time.time()
thread_list = []
for i in range(5):
t = threading.Thread(target=run, args=(i,))
thread_list.append(t)
for t in thread_list:
t.start()
for t in thread_list:
t.join()
print('主线程执行结束', threading.current_thread().name)
print('一共用时:', time.time()-s_time)
|
执行以上程序会输出如下结果:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
主线程开始执行: MainThread
Thread-1 线程开始了!
Thread-1 线程结束了!
Thread-2 线程开始了!
Thread-3 线程开始了!
Thread-4 线程开始了!
Thread-5 线程开始了!
Thread-2 线程结束了!
Thread-3 线程结束了!
Thread-4 线程结束了!
Thread-5 线程结束了!
主线程执行结束 MainThread
一共用时: 4.1290283203125
|
类方式
使用类方式需要写一个类,继承自threading.Thread类,然后重写run()方法。
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
import threading
import time
class MyThread(threading.Thread):
def __init__(self, sec):
super().__init__()
self.sec = sec
def run(self):
print('%s 线程开始了!' %threading.current_thread().name)
time.sleep(self.sec)
print('%s 线程结束了!' %threading.current_thread().name)
if __name__ == '__main__':
print('主线程开始执行', threading.current_thread().name)
s_time = time.time()
my_thread_list = []
for i in range(5):
my_thread = MyThread(i)
my_thread_list.append(my_thread)
for i in my_thread_list:
i.start()
for i in my_thread_list:
i.join()
print('一共用时:', time.time()-s_time)
print('主线程结束执行', threading.current_thread().name)
|
执行以上程序会输出如下结果:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
主线程开始执行 MainThread
Thread-1 线程开始了!
Thread-1 线程结束了!
Thread-2 线程开始了!
Thread-3 线程开始了!
Thread-4 线程开始了!
Thread-5 线程开始了!
Thread-2 线程结束了!
Thread-3 线程结束了!
Thread-4 线程结束了!
Thread-5 线程结束了!
一共用时: 4.059479713439941
主线程结束执行 MainThread
|
五、Thread实例对象的方法
start(): 启动线程。
isAlive(): 判断线程是否活动的。
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
from threading import Thread
import time
class MyThread(Thread):
def __init__(self, threadname):
Thread.__init__(self, name=threadname)
def run(self):
time.sleep(5)
print('%s运行结束'%self.getName())
#建立子线程t
t=MyThread('子线程')
#启动线程
t.start()
#判断线程是否活动的。
if t.is_alive():
print("子线程运行中")
else:
print("子线程运行结束")
print("主线程运行结束")
|
执行以上程序会输出如下结果:
1
2
3
|
子线程运行中
主线程运行结束
子线程运行结束
|
getName(): 获取线程名。
setName(): 设置线程名。
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
from threading import Thread
import time
class MyThread(Thread):
def __init__(self, threadname):
Thread.__init__(self, name=threadname)
def run(self):
time.sleep(5)
#getName()获取线程名
print('%s运行结束'%self.getName())
#建立子线程t
t=MyThread('子线程')
#启动线程
t.start()
#设置线程名字
t.setName('子线程t')
print("主线程运行结束")
|
执行以上程序会输出如下结果:
守护线程,表示该线程是不重要的,主线程退出时不需要等待这个线程执行完成。
isDaemon(bool): 判断是否是守护线程(默认False)。
setDaemon(bool): 设置是守护线程(默认False)。
默认False,主线程不回收此线程;设为True时,主线程结束时会将回收此线程,无论此线程是否完成。这样做的意义在于:避免子线程无限死循环,导致退不出程序。
注意,需要在线程start之前设置setDaemon(),否则会抛出RuntimeError异常。
不设置setDaemon(),默认是False。
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
from threading import Thread
import time
class MyThread(Thread):
def __init__(self, threadname):
Thread.__init__(self, name=threadname)
def run(self):
time.sleep(5)
print('%s运行结束'%self.getName())
t=MyThread('子线程')
t.start()
if t.is_alive():
print("主线程执行完毕")
else:
print("主线程等待子线程")
|
执行以上程序会输出如下结果:
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
from threading import Thread
import time
class MyThread(Thread):
def __init__(self, threadname):
Thread.__init__(self, name=threadname)
def run(self):
time.sleep(5)
print('%s运行结束'%self.getName())
t=MyThread('子线程')
t.setDaemon(True) #设置守护线程,主线程结束时,强制子线程结束
t.start()
if t.is_alive():
print("主线程执行完毕")
else:
print("主线程等待子线程")
|
执行以上程序会输出如下结果:
join([timeout])
阻塞主线程,直到调用此方法的线程终止或到达指定的timeout(可选参数)。主线程等待其返回然后再继续执行。
例如,没有join处理的时候
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
from threading import Thread
import time
class MyThread(Thread):
def __init__(self, threadname):
Thread.__init__(self, name=threadname)
def run(self):
time.sleep(5)
print('%s运行结束'%self.getName())
t=MyThread('子线程')
t.start()
print("主线程在等待子线程")
print("主线程运行结束")
|
执行以上程序会输出如下结果:
1
2
3
|
主线程在等待子线程
主线程运行结束
子线程运行结束
|
例如,有join处理的时候
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
from threading import Thread
import time
class MyThread(Thread):
def __init__(self, threadname):
Thread.__init__(self, name=threadname)
def run(self):
time.sleep(5)
print('%s运行结束'%self.getName())
t=MyThread('子线程')
t.start()
print("主线程在等待子线程")
#子线程t阻塞主线程。子线程运行完毕后,再继续运行主线程
t.join()
print("主线程运行结束")
|
执行以上程序会输出如下结果:
1
2
3
|
主线程在等待子线程
子线程运行结束
主线程运行结束
|
join有一个timeout参数:
当设置守护线程时(也就是setDaemon(true)),含义是主线程对于子线程等待timeout的时间将会杀死该子线程,最后退出程序。所以说,如果有10个子线程,全部的等待时间就是每个timeout的累加和。简单的来说,就是给每个子线程一个timeout的时间,让他去执行,时间一到,不管任务有没有完成,直接杀死。
没有设置守护线程时(也就是setDaemon(false)),主线程将会等待timeout的累加和这样的一段时间,时间一到,主线程结束,但是并没有杀死子线程,子线程依然可以继续执行,直到子线程全部结束,程序退出。
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
from threading import Thread
import time
class MyThread(Thread):
def __init__(self, threadname):
Thread.__init__(self, name=threadname)
def run(self):
time.sleep(5)
print('%s运行结束'%self.getName())
my_thread_list = []
for i in range(5):
my_thread = MyThread(i)
my_thread_list.append(my_thread)
for i in my_thread_list:
i.start()
print("主线程在等待子线程")
#子线程阻塞主线程。子线程运行完毕后,再继续运行主线程
for i in my_thread_list:
i.join(1)
print("主线程运行结束")
|
执行以上程序会输出如下结果:
1
2
3
4
5
6
7
|
主线程在等待子线程
主线程运行结束
Thread-1运行结束
1运行结束
2运行结束
3运行结束
4运行结束
|
转载请注明本网址。