阻塞线程和守护线程:
joIn的作用:join所完成的工作就是线程同步,即主线程任务结束之后,进入阻塞状态,一直等待其他的子线程执行结束之后,主线程再终止
setDaemon的作用:这个方法基本和join是相反的。不管子线程是否完成,都要和主线程—起退出。将线程声明为守护线程,必须在start()方法调用之前设置
如果不设置为守护线程,程序会被无限挂起。当我们在程序运行中,执行一个主线程,如果主线程又创建一个子线程,主线程和子线程就分兵两路,分别运行,那么当主线程完成想退出时,会检验子线程是否完成。如果子线程未完成,则主线程会等待子线程完成后再退出
Threading模块的基础方法
~run():用以表示线程活动的方法
~start():启动线程
~join():等待至子线程终止
~isAlive():返回线程是否活动的
~getName():返回线程名称
~setName() : 设置线程名称
Queue模块中的常用方法:
Queue.qsize() 返回队列的大小
Queue.empty() 如果队列为空,返回True,反之False
Queue.full() 如果队列满了,返回True,反之False
Queue.full 与 maxsize 大小对应
Queue.get([block[, timeout]])获取队列,timeout等待时间
Queue.get_nowait() 相当Queue.get(False)
Queue.put(item, block=True, timeout=None) 写入队列,timeout等待时间
Queue.put_nowait(item) 相当 Queue.put(item, False)
Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号。每task_done一次 就从队列里删掉一个元素,这样在最后join的时候根据队列长度是否为零来判断队列是否结束,从而执行主线程。
Queue.join() 实际上意味着等到队列为空,再执行别的操作
lock与Rlock的区别:
区别一:Lock被称为原始锁,一个线程只能请求一次;RLock被称为重入锁,可以被一个线程请求多次,即锁中可以嵌套锁。
import threading
def main():
lock.acquire()
print('第一道锁')
lock.acquire()
print('第二道锁')
lock.release()
lock.release()
if __name__ == '__main__':
lock = threading.Lock()
main()
我们会发现这个程序只会打印“第一道锁”,而且程序既没有终止,也没有继续运行。这是因为Lock锁在同一线程内第一次加锁之后还没有释放时,就进行了第二次acquire请求,导致无法执行release,所以锁永远无法释放,这就是死锁。如果我们使用RLock就能正常运行,不会发生死锁的状态。
区别二:当Lock处于锁定状态时,不属于特定线程,可在另一个线程中进行解锁释放;而RLock只有当前线程才能释放本线程上的锁,不可由其他线程进行释放,所以在使用RLock时,acquire与release必须成对出现,即解铃还须系铃人。
一句话总结就是Lock不能套娃,RLock可以套娃;Lock可以由其他线程中的锁进行操作,RLock只能由本线程进行操作。
实际代码:
# 脚本执行指定数量
import sys
import time
import threading
import numpy as np
from cases_peroformance_gateway.performance_settings import threads, exception_list, all_response_list, thread_number, \
repeat_time
from utilities.settings import MICRO_SERVICE_HOST_GATEWAY, MICRO_SERVICE_HOST_GATEWAY_PORT
from cases_peroformance_gateway.cases_performance_authentication_service.authentication_service_get_token import \
get_response, get_logger_error, get_logger_result, get_current_file_name
queue_lock = threading.Lock()
class MyThread(threading.Thread):
def __init__(self, thread_id, loop_time):
threading.Thread.__init__(self)
self.thread_id = thread_id
self.loop_time = loop_time
def run(self):
for i in range(0, self.loop_time):
# 获取接口response
try:
single_request_start_time_count = time.perf_counter()
get_response(thread_name=str(self.thread_id) + f'_{
i + 1}')
single_request_end_time_count = time.perf_counter()
# 计算单词request耗时
single_request_spend_time = single_request_end_time_count - single_request_start_time_count
# 输出线程id,单次request到response耗时
single_response = [str(self.thread_id) + f'_{
i + 1}', str(single_request_spend_time)]
# 将单词输入加入列表
all_response_list.append(single_response)
# 对返回异常进行处理
except Exception:
exc_type, exc_value, exc_traceback_obj = sys.exc_info()
print("exc_type: %s" % exc_type)
print("exc_value: %s" % exc_value)
print("exc_traceback_obj: %s" % exc_traceback_obj)
actual = str(exc_value)
current_error_thread_name = str(self.thread_id) + f'_{
i + 1}'

本文深入介绍了Python的Threading模块,包括线程的阻塞与守护、join方法、线程同步,以及Queue模块的常用方法。通过实例展示了线程同步与队列管理在并发执行任务中的应用,如使用Lock和RLock防止死锁,以及多线程任务的性能分析。此外,还探讨了Lock与RLock的区别,以及它们在多线程环境中的重要性。
最低0.47元/天 解锁文章

253

被折叠的 条评论
为什么被折叠?



