并发编程—线程
1. 线程
1.1 什么是线程
在操作系统中,每个进程都有一个地址空间, 且默认有一个控制线程,cpu真正的执行单位是线程。
如果把操作系统比作工厂,那么进程就是车间,每个车间里都有流水线,即进程,流水线都需要电源驱动,这个电源就是CPU 。
1.2 线程与进程区别
-
过程的区别
线程:代码的执行过程
进程:资源的申请与销毁,是资源的整合
-
内存空间的区别
进程:内存空间彼此隔离
线程:同一进程下的多个线程共享资源
-
创建速度
进程:需要申请资源,开辟空间,速度较慢
线程:只是告诉操作系统一个执行方案,速度很快、
1.3 开启线程的两种方式
-
方式一(推荐)
from threading import Thread def task(): print("子线程") t = Thread(target=task) t.start()
-
方式二
from threading import Thread class MyThread(Thread): def run(self): print("子线程") t = MyThread() t.start()
1.4 线程与进程的区别(开启速度与内存空间)
-
开启速度
# 进程开启速度 import time from multiprocessing import Process def task(): print('子进程开始') time.sleep(2) print('子进程结束') if __name__ == '__main__': p = Process(target=task) p.start() print('主进程')
# 执行结果 主进程 子进程开始 子进程结束
# 线程开启速度 import time from threading import Thread def task(): print('子线程开始') time.sleep(2) print('子线程结束') t = Thread(target=task) t.start() print('主线程')
# 执行结果 子线程开始 主线程 子线程结束
总结:进程开启后需要申请资源,开辟内存空间,速度较慢
线程开启后CPU只需执行线程代码,速度很快
-
内存空间
from threading import Thread x = 0 def task(): global x x = 1 t = Thread(target=task) t.start() print(x) # 1
总结:进程:内存空间彼此隔离,进程间通信需要IPC方式,即使用磁盘或内存通信
线程:同一进程下的线程共享同一内存空间,共享这块空间内的所有资源
1.5 线程的join用法
- t.join:阻塞,等待线程t结束后继续往下执行
import time
from threading import Thread
def task():
print('子线程开始')
time.sleep(2)
print('子线程结束')
t = Thread(target=task)
t.start()
t.join() # 阻塞,等待子线程结束
print('主线程')
# 执行结果
子线程开始
子线程结束
主线程
# 多个join的运行结果
import time
from threading import Thread
def task(name, time):
print(f'{name}开始')
time.sleep(time)
print(f'{name}结束')
start = time.time()
t1 = Thread(target=task, args=('子线程1', 1))
t2 = Thread(target=task, args=('子线程2', 2))
t3 = Thread(target=task, args=('子线程3', 3))
t1.start()
t2.start()
t3.start()
t1.join()
t2.join()
t3.join()
end = time.time()
print(end - start) # 3s多一点点
1.6 线程的其他方法
- currentThread:当前所在线程
- enumerate:当前所有线程
- activeCount:当前线程数量
import time
from threading import Thread, currentThread, enumerate, activeCount
def task():
print('子线程开始')
time.sleep(2)
print('子进程结束')import time
from threading import Thread, currentThread, enumerate, activeCount
def task():
print('子线程开始')
time.sleep(2)
print('子进程结束')
print(currentThread()) # 当前所在线程 <Thread(Thread-1, started 23360)>
print(enumerate()) # 当前所有的线程 [<_MainThread(MainThread, stopped 2664)>, <Thread(Thread-1, started 23360)>]
t = Thread(target=task)
t.start()
print(currentThread()) # 当前所在线程 <_MainThread(MainThread, started 2664)>
print(enumerate()) # 所有的线程 [<_MainThread(MainThread, started 2664)>, <Thread(Thread-1, started 23360)>]
print(activeCount()) # 当前的线程数量 2
# 运行结果
子线程开始
<_MainThread(MainThread, started 2664)>
[<_MainThread(MainThread, started 2664)>, <Thread(Thread-1, started 23360)>]
2
子进程结束
<Thread(Thread-1, started 23360)>
[<_MainThread(MainThread, stopped 2664)>, <Thread(Thread-1, started 23360)>]
1.7 守护线程
守护线程:守护进程的运行周期,即进程结束时(进程内所有线程与子进程都结束)守护线程也结束
import time
from threading import Thread
from multiprocessing import Process
def daem():
print('守护线程开始')
time.sleep(10)
print('守护线程结束')
def task():
print('子线程开始')
time.sleep(2)
print('子线程结束')
def task2():
print('子进程开始')
time.sleep(5)
print('子进程结束')
if __name__ == '__main__':
p = Process(target=task2)
p.start()
d = Thread(target=daem)
t = Thread(target=task)
d.daemon = True
d.start()
t.start()
print('主线程')
# 执行结果
守护线程开始
主线程
子线程开始
子进程开始
子线程结束
子进程结束