一、 线程与进程的比较:
1.1 线程与进程:
线程:
线程是进程中的一个单位
线程是计算机中被CPU调度的最小单位,开销小
轻型进程 轻量级的进程
在同一个进程中的多个线程是可以共享公有数据
线程的开启\销毁\切换都比进程要高效很多
进程:
计算机中最小的资源分配单位
数据隔离 开销大
1.2 为什么要使用线程:
开启进程 关闭进程 切换进程都需要时间
你的电脑的资源还是有限的
开启过多的进程会导致你的计算机崩溃
多个进程与多个线程都可以利用多核(多个CPU)处理数据
1.3 python当中的多线程:
不能访问多个cpu,是Cpython解释器导致
Cpython解释器存在全局解释器锁(GIL-Global Interpreter Lock),导致了同一时刻只能有一个线程访问CPU
jpython pypy解释器中的多线程是可以访问多核(多个CPU)
二、 dis模块:
查看Python解释器运行的底层代码块对应的字节码指令序列
示例:
#示例:
from dis importdisdeffunc():
a=[]
a.append(1)
dis(func)
View Code
三、 创建线程:
#示例(无参数):
importosimporttimefrom threading importThreaddeffunc():
time.sleep(1)print('in func', os.getpid())print('in main', os.getpid())for i in range(10):
Thread(target=func).start() #创建10个线程
无参数创建
#示例(参数):#创建10个子线程:
importosimporttimefrom threading importThreaddef 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参数传递到自线程
带参数实现
四、 进程与线程之间的内存开销比较:
主线程是在进程中创建多个子线程,开销小
主进程会创建多个子进程,开销大
#线程与进程之间的开销:
importtimefrom multiprocessing importProcessfrom threading importThreaddeffunc(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 int_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 inp_l:
t.join()print('Process', time.time() - p_start) #进程的时间差 Process 2.994523525238037
View Code
五、 进程与线程在内存中的数据分配:
线程之间共有数据共享
进程中数据都是私有,不共享
#线程与线程和进程与进程之间数据使用比较:
#多个线程之间的全局变量是共享的:
from threading importThread
tn= 0 #全局变量
deffunc():globaltn
tn+= 1t_l=[]for i in range(100):
t= Thread(target=func)
t.start()
t_l.append(t)for t int_l:
t.join()print("Thread:", tn) #Thread: 100
#进程之间数据隔离:#进程之间的数据不能共享,在子进程中数据的修改不能改变全局变量的值(可以通过Manager类修改)
from multiprocessing importProcess
pn= 0 #全局变量
deffunc():globalpn
pn+= 1
if __name__ == '__main__':
p_l=[]for i in range(100):
p= Process(target=func)
p.start()
p_l.append(p)for p inp_l:
p.join()print("Process:", pn) #Process: 0
View Code
六、 线程的其他方法:
6.1 active_count类:
线程没有terminate 不能强制结束,主线程等待直到子线程结束
active_count(): 查看当前正在工作的线程个数
#示例:
importosimporttimefrom threading importThread, active_countdeffunc():
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 :查看线程号
#示例:
importosfrom threading importThread, currentThread, activeCount, enumeratedeffunc():
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 :
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