多线程
- 线程和进程的区别:
1.线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位
2.一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线
3.进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包
括代码段,数据集,堆等)及一些进程级的资源(如打开文件和信号等),某进程内的线程在其他进程不可见
4.调度和切换:线程上下文切换比进程上下文切换要快得多 - 创建多线程
- 用函数的形式
import threading # 使用线程需要用导入的模块
import time
def text(x): # 为线程定义一个函数
print(x)
time.sleep(2) # sleep(secs)函数可以实现令当前执行的线程暂停 secs 秒后再继续执行。
# 所谓暂停,即令当前线程进入阻塞状态,当达到 sleep() 函数规定的时间后,再由阻塞状态转为就绪状态,等待 CPU 调度。
# text(1)
# text(2)
t1 = threading.Thread(target=text, args=(1, )) # 创建线程
t2 = threading.Thread(target=text, args=(2, ))
t1.start() # 启动线程活动
t2.start()
结果:
1
2
- 以类的形式
import threading # 使用线程需要用导入的模块
import time
class MyThread(threading.Thread): # 为线程定义一个类,并继承父类threading.Thread
def __init__(self, n):
super(MyThread, self).__init__() # 此类初始化后,将父类的初始化覆盖掉了,因此此处需要父类初始化
self.n = n
def run(self): # 用以表示线程活动的方法,把要执行的代码写到run函数里面 线程在创建后会直接运行run函数
print("以类的方式创建多线程", self.n)
time.sleep(2)
r1 = MyThread(11) # 实例化对象
r2 = MyThread(22)
r1.start() # 启动线程活动
r2.start()
结果:
以类的方式创建多线程 11
以类的方式创建多线程 22
- 多线程中常用函数
- join(timeout=None)
作用:官方解释是直至启动的线程终止之前一直挂起,除非给出了 timeout(秒) ,否则会一直阻塞,即除非子线程也全部运行完毕,否则主线程一直挂起
可参考:Python 多线程中join()的用法
实例:
import threading
import time
def run(x):
print(f"线程{x}") # f表示格式化字符串,等效于print("线程" + str(x))
time.sleep(2)
if __name__ == '__main__':
t1 = threading.Thread(target=run, args=(1,))
t2 = threading.Thread(target=run, args=(2,))
t1.start()
t1.join() # 在启动的线程终止前一直挂起,直至所有线程执行完
t2.start()
结果(线程1打印出两秒后打印出线程2,再经两秒运行结束):
线程1
线程2
2.获取程序结束运行的时间,需要用到join()函数
print(time.time())是获取时间戳,获取从1970年0点0分0秒到现在经历了多长时间
实例:
import threading
import time
def run(x, n):
print(f"线程{x}") # f表示格式化字符串,等效于print("线程" + str(x))
time.sleep(n)
if __name__ == '__main__':
# print(time.time()) # 时间戳,从1970年0点0分0秒到现在经历了多长时间
start_time = time.time() # 获取当前时间戳
res = [] # 创建空列表用于储存线程
s = 0
for i in range(10):
if i == 9:
s = 2
t = threading.Thread(target=run, args=(i, s))
t.start()
# t.join() # 放在这得到的是每个线程单独运行所得到的时间和
res.append(t) # 将线程添加到res列表中
s += 1
for t in res: # 遍历res中的线程
t.join() # 放在这得到的是多个线程一起运行时的运行时间
# t.join() # 放在这得到的是最后一个线程运行的时间
print(f"run()函数共运行了{time.time() - start_time}秒")
结果:
线程0
线程1
线程2
线程3
线程4
线程5
线程6
线程7
线程8
线程9
run()函数共运行了8.01369595527649秒
- 线程锁
实例:
import threading
def run():
global x
lock.acquire()
x += 1
lock.release()
if __name__ == '__main__':
x = 0
res = []
lock = threading.Lock()
for i in range(100):
t = threading.Thread(target=run)
t.start()
res.append(t)
for t in res:
t.join()
print(x)
结果:
100
- 递归锁:
实例:
import threading
def run1():
global x
lock.acquire()
x += 1
lock.release()
return x
def run2():
global y
lock.acquire()
y += 1
lock.release()
return y
def run3():
lock.acquire()
res1 = run1()
res2 = run2()
lock.release()
print(res1, res2)
if __name__ == '__main__':
x = 0
y = 0
lock = threading.RLock()
for i in range(50):
t = threading.Thread(target=run3)
t.start()
while threading.active_count() != 1:
print(f"正在运行个{threading.active_count()}线程")
print("程序运行结束")