python3中常用的两个模块为:
- _thread
- threading
thread 模块已被废弃。用户可以使用 threading 模块代替。所以,在 Python3 中不能再使用"thread" 模块。为了兼容性,Python3 将 thread 重命名为 "_thread"。
- threding中库函数介绍:
threading.currentThread():
示例1.
import threading
import time
exitFlag = 0
class myThread(threading.Thread):
def __init__(self, threadID,name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
# 使用start()方法调用创建好的线程后,该实例会调用run()方法
def run(self):
print("开始线程:" + self.name)
print_time(self.name, self.counter, 5)
print("退出线程:" + self.name)
def print_time(thread_name, delay, counter):
while counter:
if exitFlag:
thread_name.exit()
time.sleep(delay)
print("%s: %s" % (thread_name, time.ctime(time.time())))
counter -= 1
# 创建新进程
thread1 = myThread(1, "thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
# 使用start方法开启新进程,之后线程会调用run()方法
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print("退出主线程")
运行结果:
示例2:
线程同步:多个线程内的数据是共享的为了让数据同一时间内只有一个线程去访问数据我们需要对数据加锁和释放锁,这就用到了therading.Lock.acquire()方法和therading.Lock.release()方法,下面是代码示例
import threading
import time
exitFlag = 0
class myThread(threading.Thread):
def __init__(self, threadID,name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
# 使用start()方法调用创建好的线程后,该实例会调用run()方法
def run(self):
print("开始线程:" + self.name)
threadLock.acquire()
print(self.name + ': Lock')
print_time(self.name, self.counter, 5)
print(self.name + ': ReleaseLock')
threadLock.release()
print("退出线程:" + self.name)
def print_time(thread_name, delay, counter):
while counter:
if exitFlag:
thread_name.exit()
time.sleep(delay)
print("%s: %s" % (thread_name, time.ctime(time.time())))
counter -= 1
threadLock = threading.Lock()
threads = []
# 创建新进程
thread1 = myThread(1, "thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
threads.append(thread1)
threads.append(thread2)
# 使用start方法开启新进程,之后线程会调用run()方法
for t in threads:
t.start()
for t in threads:
t.join()
print("退出主线程")
运行结果如下,从运行结果上可以看出,整个程序执行顺序:
1.开启thread-1线程,thread-1线程加锁
2.开启thread-2线程,因为thread-1已经获得锁,thread-2被阻塞
3.thread-1执行指令,完成指令,释放锁
4.thread-1获得锁,执行指令,完成指令,释放锁
线程优先队列(queue)
Python 的 Queue 模块中提供了同步的、线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列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() 实际上意味着等到队列为空,再执行别的操作
示例3:
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
# 使用start()方法调用创建好的线程后,该实例会调用run()方法
def run(self):
print("开始线程:" + self.name)
process_data(self.name, self.q)
print("退出线程:" + 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()
# 定义一个队列,其最大长度为10
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 work in nameList:
workqueue.put(work)
queueLock.release()
# 判断队列是非空的
while not workqueue.empty():
pass
exitFlag = 1
# 回收线程
for t in threads:
t.join()
print("退出主线程")
运行结果:
程序执行过程,多个线程去队列中获取数据,
1)每个线程在访问队列时都要先获取锁,
2)判断队列是否为空,如果不为空,从队列中获取数据,如果队列为空,则跳过,直接释放锁,
3)下一个进程再获取锁,