线程内容 / 线程开启的两种方式 / 进程vs线程创建速度 / 子线程共享资源 / 线程的join方法 / 了解进程的join / 线程其他相关用法 / 守护线程
1. 线程内容
'''
初识别线程
在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程,cpu真正的执行单位是线程
在工厂中,每个车间都有房子,而且每个车间默认就有一条流水线
操作系统 ===》工厂
进程 ===》车间
线程 ===》流水线
cpu ===》电源
线程:cpu最小的执行单位
进程:资源集合/资源单位
线程运行 = 运行代码
进程运行 = 各种资源 + 线程
右键运行:
申请内存空间,先把解释器丢进去并且把代码丢进去,运行代码(线程)
进程和线程的区别:
过程描述的区别
线程 ==》单指代码的执行过程
进程 ==》资源的申请与销毁的过程
进程内存空间彼此隔离
同一个进程下的线程共享资源
进程和线程的创建速度
进程需要申请资源开辟空间 慢
只是告诉操作系统一个执行方案
'''
2. 线程开启的两种方式
# 方式一
from threading import Thread
import time
def task():
print('线程 start')
time.sleep(2)
print('线程 end')
if __name__ == '__main__':
t = Thread(target=task)
t.start() # 告诉操作系统开一个线程 开启线程无需申请内存空间会非常快
print('主')
# 1 同一个进程下没有父子线程之分大家地位都一样。
# 2 右键运行发生了什么事情?开启了一个进程,开辟了一个内存空间,把代码都丢进去,然后运行代码(自带的主线程运行),然后又开启了一个子线程。
# 主线程结束和子线程结束没有任何必然联系,比如主线程运行结束,子线程还在运行当中。不是主线程在等待子线程结束,是进程在等待自己的所有线程结束。
# 方式二
from threading import Thread
import time
# 进程等待所有线程结束才会结束
class Myt(Thread):
def run(self):
print('子线程 start')
time.sleep(2)
print('子线程 end')
# if __name__ == '__main__':
t = Myt()
t.start()
print('主线程')
3. 进程vs线程创建速度
from threading import Thread
from multiprocessing import Process
import time
def task(name):
print(f'{name} is running')
time.sleep(3)
print(f'{name} is end')
if __name__ == '__main__':
t = Thread(target=task,args=('子线程',))
p = Process(target=task,args=('子进程',))
t.start()
p.start()
print('主')
'''
开启子线程的打印效果:
子线程 is running
主
子线程 is end
开启子进程的打印效果:
主
子进程 is running
子进程 is end
进程和线程的创建速度
开启子进程需要申请资源开辟空间 慢
开启子线程只是告诉操作系统一个执行方案 快
'''
4. 子线程共享资源
from threading import Thread
import time,os
x = 100
def task():
global x
x = 50
print(os.getpid()) # 1816
if __name__ == '__main__':
t = Thread(target=task)
t.start()
time.sleep(2)
print(x) # 50
print(os.getpid()) # 1816
# 首先子线程修改了全局变量为50,主线程等待子线程修改完毕后打印x为50
# 说明同一个进程下所有的线程共享同一份内存空间
# 主进程下的每个线程都跟主进程的pid一样
5. 线程的join方法
from threading import Thread
import time
def task():
print('子线程 start')
time.sleep(2)
print('子线程 end')
t = Thread(target=task)
t.start()
t.join() # 主线程等待子线程运行结束
print('主线程')
# 进程的join是当前线程在等子进程运行结束并不影响其他线程
from threading import Thread
import time
def task(name,n):
print(f'{name} start')
time.sleep(n)
print(f'{name} end')
t1 = Thread(target=task,args=('线程1',1))
t2 = Thread(target=task,args=('线程2',2))
t3 = Thread(target=task,args=('线程3',3))
start = time.time()
t1.start()
t2.start()
t3.start()
t1.join() # 1s
t2.join() # 1s
t3.join() # 1s
end = time.time()
print(end - start) # 3.002460479736328
# 在单核的情况下,多个线程是如何利用cpu的???
6. 了解进程的join
from multiprocessing import Process
from threading import Thread
import time
def task1():
print('进程 start')
time.sleep(5)
print('进程 end')
def task2():
print('子线程 start')
time.sleep(2)
print('子线程 end')
if __name__ == '__main__':
p = Process(target=task1)
t = Thread(target=task2)
t.start() # 开线程
p.start() # 开进程
print('子进程join开始')
p.join() # 主进程的主线程等待子进程运行结束 当前线程等待当前进程下的子进程结束,然后往下运行
print('主')
7. 线程其他相关用法
from threading import Thread,currentThread,enumerate,activeCount
import time
def task():
print('子线程 start')
time.sleep(2)
print('子线程 end')
print(enumerate()) # 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
# print(currentThread(),'子线程') # 返回当前的线程变量
if __name__ == '__main__':
t1 = Thread(target=task)
t2 = Thread(target=task)
t1.start()
t2.start()
print(t1.is_alive()) # True # 返回线程是否活动的
print(t1.getName()) # Thread-1 # 返回线程名
print(t2.getName()) # Thread-2 # 返回线程名
t1.setName('班长') # 设置线程名
print(t1.getName()) # 班长
print(currentThread().name) # MainThread
print(enumerate()) # [<_MainThread(MainThread, started 14420)>, <Thread(班长, started 3260)>, <Thread(Thread-2, started 10844)>]
print(activeCount()) # 3 # 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果
print(len(enumerate())) # 3
8. 守护线程
# 守护线程 守护的是进程的运行周期
'''
守护线程首先是一个线程
守护线程守护到当前进程运行结束
有未完成的子进程阶段会守护
有未完成的其他子线程也均会守护
守护进程首先是一个进程
守护进程守护到当前进程的最后一行代码结束
'''
from threading import Thread,enumerate,currentThread
import time
def task1():
print('守护线程 start')
print(currentThread())
time.sleep(10)
print('守护线程 end')
def task2():
print('子线程 start')
time.sleep(5)
print(enumerate())
print('子线程 end')
if __name__ == '__main__':
t1 = Thread(target=task1)
t2 = Thread(target=task2)
t1.daemon = True
t2.start()
t1.start()
print('主')
# 当主线程已经结束的时候,其他子线程没有结束的时候打印当前的活跃的线程发现有守护线程