简单的多线程—使用线程池
import time
import threading
def task_thread(counter):
print(f'线程名称:{threading.current_thread().name} 参数:{counter} 开始时间:{time.strftime("%Y-%m-%d %H:%M:%S")}')
num = counter
while num:
time.sleep(3)
num -= 1
print(f'线程名称:{threading.current_thread().name} 参数:{counter} 结束时间:{time.strftime("%Y-%m-%d %H:%M:%S")}')
if __name__ == '__main__':
print(f'主线程开始时间:{time.strftime("%Y-%m-%d %H:%M:%S")}')
#初始化3个线程,传递不同的参数
t1 = threading.Thread(target=task_thread, args=(3,))
t2 = threading.Thread(target=task_thread, args=(2,))
t3 = threading.Thread(target=task_thread, args=(1,))
#开启三个线程
t1.start()
t2.start()
t3.start()
#等待运行结束
t1.join()
t2.join()
t3.join()
print(f'主线程结束时间:{time.strftime("%Y-%m-%d %H:%M:%S")}')
获取多线程返回值—使用线程池
from concurrent.futures import ThreadPoolExecutor
import time
request_param = ['lipei_00039.mp3', 'lipei_00044.mp3', 'lipei_00047.mp3', 'lipei_00049.mp3',
'lipei_00057.mp3', 'lipei_00058.mp3', 'lipei_00059.mp3', 'lipei_00061.mp3',
'lipei_00066.mp3', 'lipei_00068.mp3', 'lipei_00070.mp3', 'lipei_00081.mp3']
# 参数times用来模拟网络请求的时间
def action(max):
print(max)
time.sleep(0.2)
return max+'_001'
if __name__ == '__main__':
executor = ThreadPoolExecutor(max_workers=2)
for data in executor.map(action, request_param):
print("in main: get page {}s success".format(data))
使用 add_done_callback() 方法来获取线程任务的返回值
from concurrent.futures import ThreadPoolExecutor
import threading
import time
# 定义一个准备作为线程任务的函数
def action(max):
my_sum = 0
for i in range(max):
print(threading.current_thread().name + ' ' + str(i))
my_sum += i
return my_sum
# 创建一个包含2条线程的线程池
with ThreadPoolExecutor(max_workers=2) as pool:
future1 = pool.submit(action, 50) # 向线程池提交一个task, 50会作为action()函数的参数
future2 = pool.submit(action, 100) # 向线程池再提交一个task, 100会作为action()函数的参数
def get_result(future):
print(future.result())
future1.add_done_callback(get_result) # 为future1添加线程完成的回调函数
future2.add_done_callback(get_result) # 为future2添加线程完成的回调函数
print('--------------')
Exectuor 还提供了一个 map(func, *iterables, timeout=None, chunksize=1) 方法,该方法的功能类似于全局函数 map(),区别在于线程池的 map() 方法会为 iterables 的每个元素启动一个线程,以并发方式来执行 func 函数。这种方式相当于启动 len(iterables) 个线程,井收集每个线程的执行结果。
from concurrent.futures import ThreadPoolExecutor
import threading
import time
# 定义一个准备作为线程任务的函数
def action(max):
my_sum = 0
for i in range(max):
print(threading.current_thread().name + ' ' + str(i))
my_sum += i
return my_sum
# 创建一个包含4条线程的线程池
with ThreadPoolExecutor(max_workers=4) as pool:
# 使用线程执行map计算
# 后面元组有3个元素,因此程序启动3条线程来执行action函数
results = pool.map(action, (50, 100, 150))
print('--------------')
for r in results:
print(r)
添加进度条(不是很准,但是能够起到参考作用)
from concurrent.futures import ThreadPoolExecutor
import time, sys, csv
def func(msg):
print("raw:", msg)
time.sleep(0.8)
return msg + '_001'
request_params = ['lipei_00006.mp3', 'lipei_00007.mp3', 'lipei_00012.mp3',
'lipei_00021.mp3', 'lipei_00027.mp3', 'lipei_00028.mp3',
'lipei_00039.mp3', 'lipei_00044.mp3', 'lipei_00047.mp3',
'lipei_00057.mp3', 'lipei_00058.mp3', 'lipei_00059.mp3']
# 创建一个包含4条线程的线程池
with ThreadPoolExecutor(max_workers=4) as pool:
scale = len(request_params)
results = pool.map(func, request_params) # 使用线程执行map计算
Results = []
for i, r in enumerate(results):
a = '#' * int(i)
b = '.' * (int(scale) - int(i))
c = (i / scale) * 100
Results.append(r)
sys.stdout.write("{:^3.2f}%[{}->{}]".format(c, a, b))
sys.stdout.flush()
print('done!')
# 保存返回值
if len(Results) > 1:
with open("./Results .csv", 'w', newline='') as csvfile:
write = csv.writer(csvfile)
write.writerow(Results)
else:
print('download ovor OK!')