一、使用场景

大家都知道python的多线程不是真正的多线程,但是对于io类型的任务,多线程还是能发挥作用的。那么多个线程之间是如何进行变量共享的呢,很多时候我们可以借助queue模块,方便。今天就做一个学习。

二、threading模块

Python的多线程还是主要使用标准库threading,该库提供了更高级别、功能更全面的线程管理。
该模块提供的主要方法:

threading.currentThread(): 返回当前的线程变量。
threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。

除了使用方法外,threading模块同样提供了Thread类来处理线程,Thread类提供了以下方法:

run(): 用以表示线程活动的方法。
start():启动线程活动。
join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。
isAlive(): 返回线程是否活动的。
getName(): 返回线程名。
setName(): 设置线程名。

Demo

# encoding: utf-8


"""
@python: v3.5.4
@author: hutong
@file: countthread.py
@time: 2019/07/06 下午11:18
"""

import threading
import time
 
def run(n):
   print("task", n)
   time.sleep(5)   #此时子线程停1s


threads_list = []
for i in range(3):
    t= threading.Thread(target=run, args=("t-%s" % i,))
   threads_list.append(t)
   t.start()
   print(t.getName(),threading.active_count())  # 输出当前活跃的线程数

for mythread in threads_list:
   mythread.join() #等待所有的子线程都跑完
print('all threads is done') #主线程

python 队列batch python 队列 多线程_多线程

三、queue模块

Queue模块可以用来实现多线程间通讯,让各个线程共享数据,生产者把任务放到Queue中,供消费者(线程)去使用。在python3中,Queue模块被命名为queue。

Queue的对象有:

Queue.Queue(maxsize=0):创建大小为maxsize的FIFO(First In First Out)-Queue对象,如果maxsize不设置,这个队列将是无限的。
Queue.LifoQueue(maxsize=0): 创建先入后出的对象,即栈。Queue.PriorityQueue(maxsize=0):有优先级的队列。

Queue对象的方法有:

queue对象实现一个fifo队列(其他的还有lifo、priority队列,这里不再介绍)。queue只有qsize一个构造参数,用来指定队列容量,指定为0的时候代表容量无限。主要有以下成员函数:
Queue.qsize():返回消息队列的当前空间。返回的值不一定可靠。
Queue.empty():判断消息队列是否为空,返回True或False。同样不可靠。
Queue.full():类似上边,判断消息队列是否满
Queue.put(item, block=True, timeout=None):往消息队列中存放消息。block可以控制是否阻塞,timeout指定阻塞时候的等待时间。如果不阻塞或者超市,会引起一个full exception。
Queue.put_nowait(item):相当于put(item, False).
Queue.get(block=True, timeout=None):获取一个消息,其他同put。
以下两个函数用来判断消息对应的任务是否完成。
Queue.task_done():接受消息的线程通过调用这个函数来说明消息对应的任务已完成。
Queue.join():调用线程阻塞直到所有消息对应的任务已经完成。
消息队列实例中维护的有待完成任务变量。每接收到一个消息该值自增一次。每调用一次.task_done()可以使该值减1,当待完成任务值为0的时候,join函数才会返回。

四、threading和queue结合

大家可以参考如下的一个例子尝试完成任务。
demo

-----------------------------------------------------
-----------------------------------------------------
@python: v3.5.4
@author: hutong
@file: threadingqueue.py
@time: 2019/7/6 下午12:46
"""
import threading
import time
import queue
 
#下面来通过多线程来处理Queue里面的任务:
def work(q):
   while True:
       if q.empty():
           return
       else:
           t = q.get()
           print("当前线程sleep {} 秒".format(t))
           time.sleep(t) 

def main():
    q= queue.Queue()
   for i in range(5):
       q.put(i) #往队列里生成消息
   thread_num = 5
   threads = []
   for i in range(thread_num):
       t = threading.Thread(target = work, args = (q,))
       # args需要输出的是一个元组,如果只有一个参数,后面加,表示元组,否则会报错
       threads.append(t)

   for i in range(thread_num):
       threads[i].start()
   for i in range(thread_num):
       threads[i].join()
 
if __name__ == "__main__":
       start= time.time()
       main()
       print('耗时:',time.time()-start)

python 队列batch python 队列 多线程_多线程_02


往队列里产生5条任务,启动5个线程去执行,由于是并行,所以总共耗时4s。如果更改单线程执行,那么就需要0+1+2+3+4=10s的时间。

小任务:大家可以尝试利用threading和queue完成一个上传文件到多台服务器。