上面代码示例调用多线程时需要实例化MyThread并x.start()、然后x.json(),这种使用方法显得有些麻烦,另外MyThread类的构造也并不优雅,解决这个问题的较好方法是使用Python的线程池。
线程池是预先创建线程的一种技术,线程池在还没有任务到来之前,创建一定数量的线程,放入空闲队列中,这些线程都是处于睡眠状态,但均为启动未执行状态,并不消耗CPU的资源,但是会占用较小的内存空间。当请求到来之后,缓冲池会给这次请求分配一个空闲线程,把请求传入此线程中运行进行处理。当预先创建的线程都处于运行状态,即预制线程不够时,线程池自由创建一定数量的新线程,用于处理更多的请求。当系统比较闲的时候,也通过移除一部分处于停用状态的线程。
使用线程池需要注意以下几点:
(1)线程池大小
多线程应用并非线程越多越好,需要根据系统运行的软硬件环境以及应用本身的特点决定线程池的大小。一般来说,如果代码结构合理的话,线程数目与CPU 数量相适合即可。如果线程运行时出现阻塞现象,可相应增加池的大小;如有必要可采用自适应算法来动态调整线程池的大小,以提高CPU 的有效利用率和系统的整体性能。
(2)并发错误
多线程应用要特别注意并发错误,要从逻辑上保证程序的正确性,注意避免死锁现象的发生。
(3)线程泄漏。
这是线程池应用中一个严重的问题,当任务执行完毕而线程没能返回池中就会发生线程泄漏现象。
从Python3.2开始Ptyhon标准库为提供了concurrent.futures模块,它提供了ThreadPoolExecutor和ProcessPoolExecutor两个类,轻松实现了对threading和multiprocessing模块的线程池和进程池的处理具体请参考下面代码示例。
上面代码示例说明:通过使用concurrent.futures模块中的ThreadPoolExecutor(),初始化了10个线程,然后只需要调用executor.submit()方法开启执行多线程函数,同时使用as_completed(task1)获取线程池执行的结果,需要注意的是10个线程,谁先响应那么就会先加入到结果列表中,最后再次调用max()、get_media()、min()、get_avg()方法获取性能结果。从使用线程池的过程来看,无论是代码量还是代码结构来看,相对于调用threading模块更加简洁有效。