一、 线程与进程的比较:
1.1 线程与进程:
线程:
线程是进程中的一个单位
线程是计算机中被CPU调度的最小单位,开销小
轻型进程 轻量级的进程
在同一个进程中的多个线程是可以共享公有数据
线程的开启\销毁\切换都比进程要高效很多
进程:
计算机中最小的资源分配单位
数据隔离 开销大
1.2 为什么要使用线程:
开启进程 关闭进程 切换进程都需要时间
你的电脑的资源还是有限的
开启过多的进程会导致你的计算机崩溃
多个进程与多个线程都可以利用多核(多个CPU)处理数据
1.3 python当中的多线程:
不能访问多个cpu,是Cpython解释器导致
Cpython解释器存在全局解释器锁(GIL-Global Interpreter Lock),导致了同一时刻只能有一个线程访问CPU
jpython pypy解释器中的多线程是可以访问多核(多个CPU)
二、 dis模块:
查看Python解释器运行的底层代码块对应的字节码指令序列
示例:
# 示例:
from dis import dis
def func():
a =[]
a.append(1)
dis(func)
View Code
三、 创建线程:
# 示例(无参数):
import os
import time
from threading import Thread
def func():
time.sleep(1)
print('in func', os.getpid())
print('in main', os.getpid())
for i in range(10):
Thread(target=func).start() # 创建10个线程
无参数创建
# 示例(参数):
# 创建10个子线程:
import os
import time
from threading import Thread
def func(i): # 子线程函数
time.sleep(1)
print('in func', i, os.getpid())
print('in main', os.getpid())
for i in range(20):
Thread(target=func, args=(i,)).start() # i通过args参数传递到自线程
带参数实现
四、 进程与线程之间的内存开销比较:
主线程是在进程中创建多个子线程,开销小
主进程会创建多个子进程,开销大
# 线程与进程之间的开销:
import time
from multiprocessing import Process
from threading import Thread
def func(a):
a += 1
if __name__ == '__main__':
t_start = time.time() # 线程的开启时间
t_l = []
for i in range(100):
t = Thread(target=func, args=(i,))
t.start()
t_l.append(t)
for t in t_l:
t.join()
print('thread :', time.time() - t_start) # 线程的时间差 thread : 0.03014397621154785
p_start = time.time() # 进程的开启时间
p_l = []
for i in range(100):
p = Process(target=func, args=(i,))
p.start()
p_l.append(t)
for p in p_l:
t.join()
print('Process', time.time() - p_start) # 进程的时间差 Process 2.994523525238037
View Code
五、 进程与线程在内存中的数据分配:
线程之间共有数据共享
进程中数据都是私有,不共享
# 线程与线程和进程与进程之间数据使用比较:
# 多个线程之间的全局变量是共享的:
from threading import Thread
tn = 0 # 全局变量
def func():
global tn
tn += 1
t_l = []
for i in range(100):
t = Thread(target=func)
t.start()
t_l.append(t)
for t in t_l:
t.join()
print("Thread: ", tn) # Thread: 100
# 进程之间数据隔离:
# 进程之间的数据不能共享,在子进程中数据的修改不能改变全局变量的值(可以通过Manager类修改)
from multiprocessing import Process
pn = 0 # 全局变量
def func():
global pn
pn += 1
if __name__ == '__main__':
p_l = []
for i in range(100):
p = Process(target=func)
p.start()
p_l.append(p)
for p in p_l:
p.join()
print("Process: ", pn) # Process: 0
View Code
六、 线程的其他方法:
6.1 active_count类:
线程没有terminate 不能强制结束,主线程等待直到子线程结束
active_count(): 查看当前正在工作的线程个数
# 示例:
import os
import time
from threading import Thread, active_count
def func():
time.sleep(2)
print('in func', os.getpid())
for i in range(10):
Thread(target=func).start()
print(active_count()) # 11
View Code
6. 2 currentThread, activeCount, enumerate类方法:
# currentThread类:
# currentThread().name :查看线程名
# currentThread().ident :查看线程号
# 示例:
import os
from threading import Thread, currentThread, activeCount, enumerate
def func():
t = currentThread()
print(t.getName()) # 查看线程名:Thread-1
t.setName('AAA') # 设置线程名:AAA
print(t.name, t.ident, os.getpid()) # Thread-1 7832 1960 (子线程)
tobj = Thread(target=func)
tobj.start()
print('tobj :', tobj) # tobj : <Thread(Thread-1, started 7832)>
t2 = currentThread()
print(t2.name, t2.ident, os.getpid()) # MainThread 17672 1960 (主线程)
print('主线程...')
print(t2.is_alive()) # 查看线程是否还存活
print(activeCount()) # 返回正在运行的线程数量, 与len(threading.enumerate())有相同的结果
print(enumerate()) # 返回一个正在运行的所有线程的列表
View Code