多线程

__thread模块

基础知识 开启一个新线程

_thread.start_new_thread(function, args[, kwargs]) 

例如

import _thread,time
def child(tid):
    print('Hello from thread', tid)
def parent():
    i = 0
    _thread.start_new_thread(child, (i,))
    time.sleep(3)
    print('hhe')
if __name__ == '__main__':
    parent()
>>>

Hello from thread 0
hhe  #(3s之后)

###
本例中载入_thread模块和创建线程并调用。
_thread.start_new_thread调用本身立即返回一个没有用的值,它派生出来的线程在其运行函数返回后安静的退出。用_thread模块时,大多数系统平台上整个程序退出时随之退出。上例中如果把time.sleep(3)的代码注释,则新线程的输出可能不成功。主线程就结束了,分线程也会随之结束
import \_thread, time
def action(i):                                       
    print(i ** 32)
class Power:
    def __init__(self, i):
        self.i = i
    def action(self):                               
        print(self.i ** 32)

_thread.start_new_thread(action, (2,))  #绑定简单函数             
_thread.start_new_thread((lambda: action(2)), ())   #绑定lambda表达式
obj = Power(2)
_thread.start_new_thread(obj.action, ())     #绑定方法对象        
time.sleep(2)
print('Main thread exiting.')       
###
在线程中对实例对象的状态做出任何改变,对于所有其他线程都是可见的           

同时运行多个线程

import _thread as thread, time
def counter(myId, count):                        # 线程中运行的程序
    for i in range(count):
        time.sleep(1)                            # 模拟耗时操作
        print('[%s] => %s' % (myId, i))

for i in range(5):                               # 开启5个线程
    thread.start_new_thread(counter, (i, 5))     # 每个线程中循环5次
time.sleep(6)
print('Main thread exiting.') 

线程所的概念
避免多个线程同时争夺同意资源而必须采用线程锁。

基础知识

mutex = _thread.allocate_lock()  创建锁

mutex.acquire()使用锁
.....操作要处理的对象
mutext.release()  释放锁

示例代码

import \_thread as thread, time

def counter(myId, count):                        
    for i in range(count):
        time.sleep(1)                            
        mutex.acquire()                                 #用锁
        print('[%s] => %s' % (myId, i))         
        mutex.release()                                  #解锁

mutex = thread.allocate_lock()                   # 创建一个全局锁
for i in range(5):                              
    thread.start_new_thread(counter, (i, 5))    
time.sleep(6)
print('Main thread exiting.')  

可以根据线程锁的状态来判断某个线程有没有完成耗时操作

import _thread as thread
stdoutmutex = thread.allocate_lock()
exitmutexes = [thread.allocate_lock() for i in range(10)]
#exitmutexes = [False]*10
def counter(myId, count):
    for i in range(count):
        stdoutmutex.acquire()
        print('[%s] => %s' % (myId, i))
        stdoutmutex.release()
    exitmutexes[myId].acquire()    # 标记myId线程完成任务 
    #exitmutexes[myId] = True

for i in range(10):
    thread.start_new_thread(counter, (i, 100))
for mutex in exitmutexes:                      #实时检测状态锁的状态。一旦全部锁住表示所有线程都完成任务。则循环完成
    while not mutex.locked(): pass
#while False in exitmutexes:pass 
print('Main thread exiting.')

threading

threading模块在内部使用_thread模块来实现代表线程的对象以及常用同步化工具的功能

import threading

class Mythread(threading.Thread):             # 继承Thread的子类
    def __init__(self, myId, count, mutex):
        self.myId  = myId
        self.count = count                     
        self.mutex = mutex                     # 传递来的线程锁
        threading.Thread.__init__(self)
    def run(self):                                   # 真正线程做的工作
        for i in range(self.count):            # 同步化 with语句线程锁
            with self.mutex:
                print('[%s] => %s' % (self.myId, i))

stdoutmutex = threading.Lock()                 #线程锁
threads = []
for i in range(10):
    thread = Mythread(i, 100, stdoutmutex)    
    thread.start()                             # 开始运行新的线程
    threads.append(thread)
for thread in threads:
    thread.join()                              # 等待线程结束 join
print('Main thread exiting.')

threading模块里的线程用Thread对象实现,通过提供定义线程的run方法来进行定制Python类Mythread,当我们创建一个Mythread类实例并调用其start方法时,run方法将在新的线程中执行。
Thread.join()方法可等待线程退出,采用这个方法避免主线程在子线程之前退出。

其他编程方法 可以直接利用Thread的默认run方法直接调用传给构造器的target参数的可调用对象aciton,args参数为传递给action的参数

threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)

import threading
def action(i):print(i**32)
thread = threading.Thread(target=action,arg=(2,))
thread.start()  #执行action

queue模块
queue模块提供一个标准的队列数据结构---一个先进先出的Python对象列表。队列对象自动有线程锁获取和释放操作控制,在任意给定时间只有一个线程能够修改队列

numconsumers = 2                
numproducers = 4                 
nummessages  = 4                
import _thread as thread, queue, time
safeprint = thread.allocate_lock()   
dataQueue = queue.Queue()             # 共享全局变量,没有限制大小 可以传参限制大小
def producer(idnum, dataqueue):
    for msgnum in range(nummessages):
        time.sleep(idnum)
        dataqueue.put('[producer id=%d, count=%d]' % (idnum, msgnum))        #放入队列

def consumer(idnum, dataqueue):
    while True:
        time.sleep(0.1)
        try:
            data = dataqueue.get(block=False)       #从队列里取值,如果队列为空者引发异常
        except queue.Empty:
            pass
        else:
            with safeprint:        #线程锁
                print('consumer', idnum, 'got =>', data)

if __name__ == '__main__':
    for i in range(numconsumers):
        thread.start_new_thread(consumer, (i, dataQueue))
    for i in range(numproducers):
        thread.start_new_thread(producer, (i, dataQueue))
    time.sleep(((numproducers-1) * nummessages) + 1)  #保证主线程最后退出
    print('Main thread exit.')
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容