多线程优点
多线程类似于同时执行多个不同程序,多线程运行有如下优点:
1、使用线程可以把占据长时间的程序中的任务放到后台去处理。 2、用户界面可以更加吸引人,比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度。 3、一些等待的任务实现上如用户输入、文件读写和网络收发数据等,多线程就有用了。可以释放一些珍贵的资源如内存占用等等。线程中常用的两个模块为:thread、threading。thread 模块已被废弃。用户可以使用 threading 模块代替。
threading 模块创建线程
通过直接从 threading.Thread 继承创建一个新的子类,并实例化后调用 start() 方法启动新线程,即它调用了线程的 run() 方法。
import threadingimport time#继承threading.Thread类class feiGegeThread (threading.Thread): #线程ID,线程名称,延迟时间 def __init__(self, threadID, name, delay): threading.Thread.__init__(self); self.threadID = threadID; self.name = name; self.delay = delay; #重写run方法 def run(self): print ("begin thread:" + self.name); #调用外部函数 print_time(self.name, self.delay, 3); print ("end thread:" + self.name);#定义打印时间方法:线程名字、延迟时间、打印次数def print_time(threadName, delay, counter): while counter: time.sleep(delay) print ("%s: %s" % (threadName, time.ctime(time.time()))); counter -= 1;# 创建新线程thread1 = feiGegeThread(1, "Thread-1", 1);thread2 = feiGegeThread(2, "Thread-2", 2);# 开启新线程thread1.start();thread2.start();#join方法可以防止主线程提前结束。thread1.join();thread2.join();#结果begin thread:Thread-1begin thread:Thread-2Thread-1: Sun Jun 16 10:23:48 2019Thread-2: Sun Jun 16 10:23:49 2019Thread-1: Sun Jun 16 10:23:49 2019Thread-1: Sun Jun 16 10:23:50 2019end thread:Thread-1Thread-2: Sun Jun 16 10:23:51 2019Thread-2: Sun Jun 16 10:23:53 2019end thread:Thread-2
线程同步
如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。
使用 Thread 对象的 Lock 和 Rlock 可以实现简单的线程同步,这两个对象都有 acquire 方法和 release 方法,对于那些需要每次只允许一个线程操作的数据,可以将其操作放到 acquire 和 release 方法之间。import threadingimport timeclass myThread (threading.Thread): def __init__(self, threadID, name, delay): threading.Thread.__init__(self); self.threadID = threadID; self.name = name; self.delay = delay; def run(self): print ("begin thread: " + self.name); # 获取锁,用于线程同步 threadLock.acquire(); print_time(self.name, self.delay, 3); # 释放锁,开启下一个线程 threadLock.release();def print_time(threadName, delay, counter): while counter: time.sleep(delay); print ("%s: %s" % (threadName, time.ctime(time.time()))); counter -= 1;#获取锁对象threadLock = threading.Lock();#盛放线程的列表threads = [];# 创建新线程thread1 = myThread(1, "Thread-1", 1);thread2 = myThread(2, "Thread-2", 2);# 开启新线程thread1.start();thread2.start();# 添加线程到线程列表threads.append(thread1);threads.append(thread2);# 等待所有线程完成,主线程才退出for t in threads: t.join();结果:begin thread: Thread-1begin thread: Thread-2Thread-1: Sun Jun 16 10:38:27 2019Thread-1: Sun Jun 16 10:38:28 2019Thread-1: Sun Jun 16 10:38:29 2019Thread-2: Sun Jun 16 10:38:31 2019Thread-2: Sun Jun 16 10:38:33 2019Thread-2: Sun Jun 16 10:38:35 2019
瞧,打印函数一段时间内只允许一个线程操作。
线程优先级队列(Queue)
Python 的 Queue 模块中提供了同步的、线程安全的队列类,包括先入先出的队列 Queue,后入先出的队列 LifoQueue,和优先级队列 PriorityQueue。
这些队列都实现了锁原语,能够在多线程中直接使用,可以使用队列来实现线程间的同步。import queueimport threadingimport timeexitFlag = 0class myThread (threading.Thread): def __init__(self, threadID, name, q): threading.Thread.__init__(self); self.threadID = threadID; self.name = name; self.q = q; def run(self): print ("begin thread:" + self.name); process_data(self.name, self.q); print ("end thread:" + self.name);def process_data(threadName, q): while not exitFlag: queueLock.acquire(); if not workQueue.empty(): data = q.get(); queueLock.release(); print ("%s processing %s" % (threadName, data)); else: queueLock.release(); time.sleep(1);threadList = ["Thread-1", "Thread-2", "Thread-3"];nameList = ["One", "Two", "Three", "Four", "Five"];queueLock = threading.Lock();workQueue = queue.Queue(10);threads = [];threadID = 1;# 创建新线程for tName in threadList: thread = myThread(threadID, tName, workQueue); thread.start(); threads.append(thread); threadID += 1;# 填充队列queueLock.acquire();for word in nameList: workQueue.put(word);queueLock.release();# 等待队列清空while not workQueue.empty(): pass# 通知线程是时候退出exitFlag = 1;# 等待所有线程完成for t in threads: t.join();#结果:begin thread:Thread-1begin thread:Thread-2begin thread:Thread-3Thread-3 processing OneThread-2 processing TwoThread-3 processing ThreeThread-1 processing FourThread-2 processing Fiveend thread:Thread-3end thread:Thread-1end thread:Thread-2