每个独立的线程都有一个程序运行的入口、顺序执行序列和程序的出口。但是程序不能够独立执行,必须依附在应用程序中,由应用程序提供多个线程执行控制。
每个线程都有他自己的一组CPU寄存器,称为线程的上下文,该上下文反映了线程上次运行该线程的CPU寄存器状态。
指令指针和堆栈指针寄存器是线程上下文中两个最重要的寄存器,线程总是在进程得到上下文中运行的,这些地址都用于标志拥有线程的进程地址空间中的内存。
python3线程中常用的模块:threading
目录
一、使用threading模块创建线程
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
def run(self):
print('开始线程:' + self.name)
print_time(self.name, self.counter, 5)
print('退出线程:' + self.name)
def print_time(threadName, delay, counter):
while counter:
if exitFlag:
threadName.exit()
time.sleep(delay)
print("%s:%s" % (threadName, time.ctime(time.time())))
counter -= 1
# 创建新线程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
# 开启新线程
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print("退出主线程")
'''
开始线程:Thread-1
开始线程:Thread-2
Thread-1:Mon Sep 7 16:21:57 2020
Thread-1:Mon Sep 7 16:21:58 2020
Thread-2:Mon Sep 7 16:21:58 2020
Thread-1:Mon Sep 7 16:21:59 2020
Thread-2:Mon Sep 7 16:22:00 2020
Thread-1:Mon Sep 7 16:22:00 2020
Thread-1:Mon Sep 7 16:22:01 2020
退出线程:Thread-1
Thread-2:Mon Sep 7 16:22:02 2020
Thread-2:Mon Sep 7 16:22:04 2020
Thread-2:Mon Sep 7 16:22:06 2020
退出线程:Thread-2
退出主线程
'''
thread.join()
join()方法的功能是在程序指定位置,优先让该方法的调用者使用CPU资源。该方法的语法格式如下:
thread.join([timeout])
timeout是可选参数,其功能是指定thread线程最多可以霸占CPU资源的时间(单位:秒)。如果省略,则默认直到thread执行结束(或者进入死亡状态)才释放CPU资源。
依次检验线程池中的线程是否结束,没有结束就阻塞直到线程结束,如果结束则跳转执行下一个join函数。
阻塞主进程,专注于执行多线程中的程序。
多线程多join情况下,依次执行各线程的join方法,前头结束了才执行后一个。
无参数,则等待到该线程结束,才开始执行下一个线程的join
无join的情况下,
#无thread_join
import threading
def action(*add):
for arc in add:
print(threading.current_thread().getName() + " " + arc)
my_tuple = ("tuple_1", \
"tuple_2", \
"tuple_3")
# 创建线程
thread = threading.Thread(target=action, args=my_tuple)
# 启动线程
thread.start()
# 主线程
for i in range(5):
print(threading.current_thread().getName())
'''
Thread-1 tuple_1
Thread-1 tuple_2
MainThread
Thread-1 tuple_3
MainThread
MainThread
MainThread
MainThread
'''
在这个例子中,Thread类创建了一个线程thread(线程名为“Thread-1”),任务(target)为action函数。同时主线程在执行for循环。主线程MainThread和子线程Thread-1会轮流获得CPU资源,程序运行结果如上图所示。
有join的情况下,
#无thread_join
import threading
def action(*add):
for arc in add:
print(threading.current_thread().getName() + " " + arc)
my_tuple = ("tuple_1", \
"tuple_2", \
"tuple_3")
# 创建线程
thread = threading.Thread(target=action, args=my_tuple)
# 启动线程
thread.start()
thread.join()
# 主线程
for i in range(5):
print(threading.current_thread().getName())
'''
Thread-1 tuple_1
Thread-1 tuple_2
Thread-1 tuple_3
MainThread
MainThread
MainThread
MainThread
MainThread
'''
二、线程同步
Lock的使用。使用Thread对象的Lock和Rlock可以实现简单的线程同步,这两个对象都有acquire方法和release方法,对于那些需要每次只允许一个线程操作的数据,可以将其操作放到acquire和release方法之间。
#! python
# -*- coding:utf-8 -*-
# Author:XXX
# Datetime:XXX
import threading
import time
class myThread(threading.Thread):
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self):
print("开启线程:" + self.name)
threadLock.acquire()
print_time(self.name, self.counter, 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()
print("退出主线程")
'''
开启线程:Thread-1
开启线程:Thread-2
Thread-1:Mon Sep 7 16:40:07 2020
Thread-1:Mon Sep 7 16:40:08 2020
Thread-1:Mon Sep 7 16:40:09 2020
Thread-2:Mon Sep 7 16:40:11 2020
Thread-2:Mon Sep 7 16:40:13 2020
Thread-2:Mon Sep 7 16:40:15 2020
退出主线程
'''
三、线程优先级队列(Queue)
python的Queue模块中提供了同步的、线程安全的队列类,包括FIFO队列和LIFO对立,和优先级队列PriorityQueue。
#! python
# -*- coding:utf-8 -*-
# Author:XXX
# Datetime:XXX
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("开启线程:" + 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("退出线程:" + 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("退出主线程")
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()
print("退出主线程")
'''
开启线程:Thread-1
开启线程:Thread-2
开启线程:Thread-3
Thread-3 processing OneThread-2 processing Two
Thread-1 processing Three
Thread-3 processing Four
Thread-2 processing Five
退出线程:Thread-3
退出线程:Thread-1
退出线程:Thread-2
退出主线程
开启线程:Thread-1
退出线程:Thread-1
开启线程:Thread-2
退出线程:Thread-2
退出主线程
'''