Process 进程类 Thread 线程类 二者用法相同
1.效率对比
import time
import os
from multiprocessing import Process as Thread #进程
def func():
n = 1+ 2 +3
n**2
if __name__ == '__main__':
start = time.time()
l = []
for i in range(100):
t = Thread(target=func)
t.start()
# print(t) #<Process(Process-1, started)>
l.append(t)
for t in l:
t.join()
print(time.time()-start)
import time
import os
from threading import Thread #线程
def func():
n = 1+ 2 +3
n**2
if __name__ == '__main__':
start = time.time()
l = []
for i in range(100):
t = Thread(target=func)
t.start()
# print(t)
l.append(t)
for t in l:
t.join()
print(time.time()-start)
3.661578893661499
0.02001357078552246
Process finished with exit code 0
2.线程的数据共享
import time
from threading import Thread
n = 100
def func():
global n
# time.sleep(1)
n -= 1
if __name__ == '__main__':
t = Thread(target=func)
print(n)
t.start()
print(n)
100
99
Process finished with exit code 0
3. 开启线程的另一种方式 (进程同理)
from threading import Thread
class Mythread(Thread):
def __init__(self,args):
super().__init__()
self.arg = args
def run(self):
print("in son",self.arg)
t = Mythread(123)
t.start()
4.threading模块中的其他功能
from threading import Thread,currentThread,activeCount,enumerate
import time
class Mythread(Thread):
def __init__(self,arg):
super().__init__()
self.arg = arg
def run(self):
print("in son",self.arg,currentThread)
for i in range(10):
t= Mythread(123)
t.start()
print(t.ident)
print(activeCount())
print(enumerate())
enumerate:所有线程对象组成的列表
currentThread “返回当前线程对象,对应于调用方的控制线程。如果调用者的控制线程不是通过线程模块创建的,则返回一个功能有限的虚拟线程对象。
ident(Self):“此线程的线程标识符(如果没有启动)。这是一个非零整数。请参见get_ident()函数。线程标识符可以在线程退出并创建另一个线程时循环使用。该标识符即使在线程退出之后也可用。
activeCount = active_Count “返回当前活动的线程对象的数量。返回的计数等于枚举()返回的列表的长度。
5.守护线程
守护进程 只守护主进程的代码,主进程代码结束了就结束守护,守护进程在主进程之前结束
守护线程 随着主线程(包含所有非守护的子线程)的结束才结束,守护线程是怎么结束的?
线程内部的代码执行完毕 那么就自动结束了。线程没有强制结束的方法.即没有terminate方法
import time
from threading import Thread
def func1():
while True:
print("in func")
time.sleep(0.5)
def func2():
print("start func2")
time.sleep(2)
print("end func2")
if __name__ == '__main__':
t1 = Thread(target =func1)
t2 = Thread(target=func2)
t1.setDaemon(True) #将func1设置为守护线程
t1.start()
t2.start()
print("主线程")
time.sleep(2)
print("主进程结束")
in func
start func2
主线程
in func
in func
in func
主进程结束
end func2
Process finished with exit code 0
6.0线程池引子 threading模块
import time
from threading import currentThread
from concurrent.futures import ThreadPoolExecutor
#concurrent.futures模块提供了高度封装的异步调用接口
def func(num):
print("in %s func"%num,currentThread())
time.sleep(1)
return num**2
tp= ThreadPoolExecutor(5) #ThreadPoolExecutor:线程池,提供异步调用
ret_l = [] #扩展: ProcessPoolExecutor: 进程池,提供异步调用
for i in range(30):
ret= tp.submit(func,i) #基本方法 submit(fn,*args,**kwargs)异步提交任务
ret_l.append(ret)
for ret in ret_l:
print(ret.result()) #result 提取结果
6.1线程池
提交任务:submit 阻塞直到任务完成(close+join)shutdown
获取结果 result 简便用法map,异步提交任务 回调函数 add_done_callback
submit用法
import os
import time
import random
from threading import currentThread
from concurrent.futures import ThreadPoolExecutor
def func(num):
print('in %s func'%num,currentThread())
print('in %s func'%num,os.getpid()) #线程池id
time.sleep(random.random())
return num**2
if __name__ == '__main__':
start = time.time()
tp = ThreadPoolExecutor(5) #创建一个线程池
# 如果将ThreadPoolExecutor改为ProcessPoolExecutor,则就改成了进程池,其他操作步骤完全一样
ret_l = []
for i in range(30):
ret = tp.submit(func,i) #提交任务,一次运行5个线程
ret_l.append(ret) #将这些线程都加入到列表中
tp.shutdown() # close + join 等所有的线程都执行完,再打印下面的结果
for ret in ret_l:
print(ret.result()) #result获取结果
in 0 func <Thread(ThreadPoolExecutor-0_0, started daemon 5980)>
in 0 func 2948
in 1 func <Thread(ThreadPoolExecutor-0_1, started daemon 9856)>
in 1 func 2948
in 2 func <Thread(ThreadPoolExecutor-0_2, started daemon 14348)>
in 2 func 2948
in 3 func <Thread(ThreadPoolExecutor-0_3, started daemon 3412)>
in 3 func 2948
in 4 func <Thread(ThreadPoolExecutor-0_4, started daemon 13952)>
in 4 func 2948
......
0
1
4
9
16
......
Process finished with exit code 0
map用法如下,其他程序同上
# if __name__ == '__main__':
# tp = Pool(2)
# ret = tp.map(func,range(6))
# for i in ret:
# print(i)
回调函数
from threading import currentThread
from concurrent.futures import ThreadPoolExecutor as Pool
def func1(num):
print('in func1 ',num,currentThread())
return num*'*'
def func2(ret):
print('--->',ret.result(),currentThread())
tp = Pool(5)
print('主 : ',currentThread())
for i in range(10):
tp.submit(func1,i).add_done_callback(func2)
# 回调函数收到的参数是需要使用result()获取的
# 回调函数是由谁执行的? 主线程
主 : <_MainThread(MainThread, started 6628)>
in func1 0 <Thread(ThreadPoolExecutor-0_0, started daemon 10692)>
---> <Thread(ThreadPoolExecutor-0_0, started daemon 10692)>
in func1 1 <Thread(ThreadPoolExecutor-0_0, started daemon 10692)>
---> * <_MainThread(MainThread, started 6628)>
in func1 2 <Thread(ThreadPoolExecutor-0_0, started daemon 10692)>
---> ** <_MainThread(MainThread, started 6628)>
......
Process finished with exit code 0
总结:ThreadPoolExecutor线程池模块和ProcessPoolExecutor进程池模块中的方法都一样,即在开启的时候只需要改下模块的名字,就能实现相应的功能。不同的是Pool进程池模块不具备这些方法,但Pool和ProcessPoolExecutor都为进程池,实现的功能也相同,只不过方法不同。