叁拾
一、线程
初识别线程:
在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程,cpu真正的执行单位是线程。
在工厂中, 每个车间都有房子,而且每个车间默认就有一条流水线。
操作系统 => 工厂
进程 => 车间
线程 => 流水线
cpu => 电源
线程:cpu最小的执行单位。
进程:资源集合/资源单位。
线程运行 = 运行代码
进程运行 = 各种资源 + 线程
右键运行:申请内存空间,先把解释器丢进去并且把代码丢进去(进程做的),运行代码(线程)。
进程和线程的区别:
过程描述的区别:
线程--》单指代码的执行过程
进程--》资源的申请与销毁的过程
进程内存空间彼此隔离,同一个进程下的线程共享资源。
进程和线程的创建速度:
进程需要申请资源开辟空间,速度慢。而线程只是告诉操作系统一个执行方案,速度快。
二、线程开启的两种方式
threading模块与multiprocess模块接口相似,在使用方面也有很大的相似性(threading.Thread (group=None, target=None, name=None, args= (),kwargs=None, *,daemon=None))。
创建线程的方式与创建进程的方式相似,有两种,分别是定义一个线程函数,和创建一个类的方法。
2.1 方式一
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('主')
start
主
end
2.2 方式二
from threading import Thread
import time
class Task(Thread):
def run(self):
print('start')
time.sleep(2)
print('end')
t = Task()
t.start()
print('主')
start
主
end
三、子进程与子线程的创建速度
进程需要申请资源开辟空间,速度慢。而线程只是告诉操作系统一个执行方案,速度快。
from threading import Thread
from multiprocessing import Process
import time
def task(name):
print(f'{name}is running')
time.sleep(2)
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
四、子线程共享资源
同一进程下的线程共用同一名称空间。
from threading import Thread
import time, os
x = 100
def task():
global x
x = 50
print(os.getpid())
if __name__ == '__main__':
t = Thread(target=task)
t.start()
time.sleep(2)
print(x)
print(os.getpid())
12948
50
12948
五、线程的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('主线程')
start
end
主线程
线程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()
t2.join()
t3.join()
end = time.time()
print(end - start)
线程1 start
线程2 start
线程3 start
线程1 end
线程2 end
线程3 end
3.002138614654541
六、进程的线程的join方法
from multiprocessing import Process
from threading import Thread
import time
def task():
print('进程开启')
time.sleep(5)
print('进程结束')
def taskk():
print('子线程开启')
time.sleep(2)
print('子线程结束')
if __name__ == '__main__':
p = Process(target=task)
t = Thread(target=taskk)
p.start()
t.start()
print('子进程join开始')
p.join()
print('主')
子线程开启
子进程join开始
进程开启
子线程结束
进程结束
主
七、线程的其他方法
Thread实例对象的方法:
- isAlive():返回线程是否存活。
- getName():返回线程名。
- setName():设置线程名。
threading模块提供的方法:
- threading.currentThread():返回当前线程变量。
- threading.enumerate():返回一个包含正在运行的线程list。
- threading.activeCount():返回正在运行的现成的数量,与len(threading.enumerate())有相同结果。
from threading import Thread,currentThread,enumerate,activeCount
import time
def task():
print('子线程 start')
time.sleep(2)
print('子线程 end')
print(enumerate())
if __name__ == '__main__':
t1 = Thread(target=task)
t2 = Thread(target=task)
t1.start()
t2.start()
print(t1.is_alive())
print(t1.getName())
print(t2.getName())
t1.setName('班长')
print(t1.getName())
print(currentThread().name)
print(enumerate())
print(activeCount())
print(len(enumerate()))
子线程 start
子线程 start
True
Thread-1
Thread-2
班长
MainThread
[<_MainThread(MainThread, started 2344)>, <Thread(班长, started 3936)>, <Thread(Thread-2, started 1560)>]
3
3
子线程 end
子线程 end
[<_MainThread(MainThread, stopped 2344)>, <Thread(班长, started 3936)>, <Thread(Thread-2, started 1560)>]
[<_MainThread(MainThread, stopped 2344)>, <Thread(班长, started 3936)>]
八、守护线程
主进程在其代码结束后就已经算运行完毕了(守护进程在此时就被回收),然后主进程会一直等非守护的子进程都运行完毕后回收子进程的资源(否则会产生僵尸进程),才会结束。
主线程在其他非守护线程运行完毕后才算运行完毕(守护线程在此时就被回收)。因为主线程的结束意味着进程的结束,进程整体的资源都将被回收,而进程必须保证非守护线程都运行完毕后才能结束。
from threading import Thread,enumerate,currentThread
import time
def task():
print('守护线程开始')
print(currentThread())
time.sleep(10)
def taskk():
print('子线程 start')
time.sleep(5)
print(enumerate())
print('子线程 end')
if __name__ == '__main__':
t1 = Thread(target=task)
t2 = Thread(target=taskk)
t1.daemon = True
t2.start()
t1.start()
print('主')
子线程 start
守护线程开始
主
<Thread(Thread-1, started daemon 10048)>
[<_MainThread(MainThread, stopped 8408)>, <Thread(Thread-2, started 1988)>, <Thread(Thread-1, started daemon 10048)>]
子线程 end