- 概念
- 以抛异常的形式实现,达到线程结束的目的
- 线程基础
- 使用线程可以把占据长时间的程序中的任务放到后台去处理
- 每个独立的进程有一个程序运行的入口,顺序执行序列和程序的出口
- 线程不能独立运行,必须依存在应用程序中,由应用程序提供多个线程执行控制
- 线程的结束
- 一般依靠线程函数的自然结束
- 也可以在线程函数中调用thread.exit(),抛出SystemExit exception,达到退出线程的目的
- 线程模块
- thread 标准库 提供低级别,原始线程及简单锁
- threading 标准库, 其提供以下方法
- threading.currentThread() 返回当前线程变量
- threading.enumerate() 返回一个包含正在运行的线程list
- threading.activdCount() 返回正在运行的线程数量
- threading.Thread类来处理线程,有以下方法
- run()
- start()
- join([time]) 阻塞调用线程
- 等待至线程中止
- 阻塞调用线程直到线程的join()方法被调用中止,正常退出或抛出未处理的异常或是可选的超时发生
- isAlive()
- getAlive()
- getName()
- setName()
- python 线程
- 函数式
thread.start_new_thread ( function, args[, kwargs] )
- 线程函数,tuple类型的线程函数参数,可选的关键字参数
- 类对象的形式
- threading.Thread
- 同java类似,也需要启动线程,后台线程执行run方法
- 函数式
- 多线程会造成线程竞争资源,会造成数据不一致
- 线程同步
- 原因:竞争性获取CPU资源
- 锁的概念
- threading.Lock, threading.Rlock 类对象
- acquire与release方法
- 锁的状态
- 锁定和未锁定
- 原理
- 访问共享数据时,先获取锁定
- 若有别的线程获取了锁,那么让当前线程在访问同步数据时则暂停,即同步阻塞
- 别线程释放锁后,再访问,基本流程:访问 -> 获取锁 -> 使用共享数据 -> 释放锁 -> 访问结束
- 线程执行流程
- 创建线程 -> 开启线程 -> 等待系统调度
- 线程同步
- 线程优先级队列
-
Queue模块提供了同步的,线程安全的队列类,实现了锁原语
- 先入先出队列
Queue
- 后入先出队列
LifoQueue
- 优先级队列
PriorityQueue
- 先入先出队列
-
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) 写入队列,timeout等待时间
- Queue.put_nowait(item) 相当Queue.put(item, False)
- Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号
- Queue.join() 实际上意味着等到队列为空,再执行别的操作
-
补充python多线程thread join() 作用
- join方法的阻塞,等待子线程结束
- 依次检验线程池中的线程是否结束,没有结束就阻塞直到线程结束,如果结束则跳转执行下一个线程的join函数。
- 阻塞主进程,专注于执行多线程中的程序。
- 多线程多join的情况下,依次执行各线程的join方法,前头一个结束了才能执行后面一个。
- 无参数,则等待到该线程结束,才开始执行下一个线程的join。
- 参数timeout为线程的阻塞时间,如 timeout=2 就是罩着这个线程2s 以后,就不管他了,继续执行下面的代码。
-
示例代码
# coding: utf-8
import Queue
import threading
import time
exitFlag = 0
class 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 "Starting " + self.name
process_data(self.name,self.q)
print "Exiting " + 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()
print "Exiting Main Thread"