大家好,今天来为大家分享Python编程教程(八):深入多线程与队列应用的一些知识点,和的问题解析,大家要是都明白,那么可以忽略,如果不太清楚的话可以看看本篇文章,相信很大概率可以解决您的问题,接下来我们就一起来看看吧!
每个独立的线程都包含一个程序运行入口、一个顺序执行序列和一个程序运行出口。线程必须存在于程序中,不能独立于程序运行!
每个线程都有自己的一组CPU 存储,称为线程上下文,它反映了线程上次运行的CPU 寄存器的状态。指令指针和堆栈指针寄存器是线程上下文中最重要的两个寄存器。线程总是运行在进程上下文中,这些地址用来标记拥有该线程的进程的地址空间中的内存。
Python线程
Python中主要提供了两个线程模块,thread和threading。线程模块提供了最基本、最底层的线程功能,以及简单的锁。 threading模块是对thread模块的高级封装,提供了各种线程属性和方法。下面我们就对这两个模块进行一一分析。
thread模块(不推荐使用)
线程模块中常用的函数方法:
函数名说明start_new_thread(function, args, kwargs=None) 生成一个新线程,function是该线程要运行的函数名,args是函数参数(tuple元组类型),kwargs为可选值分配一个locktype类型参数allocate_lock() 线程锁对象exit() 线程exit_count() 返回线程数。请注意,不包括主线程。因此,在主线程上运行此方法将返回0lockedlock类型的锁。返回true 意味着它被锁定。 release() 释放锁获取的锁类型对象锁。 ()Lock 举个例子:
导入线程、时间
def循环1():
print "线程数-" + str(thread._count())
我=0
尝试:
当我100:
打印我
时间.睡眠(1)
我=我+1
除了异常e:
打印e
thread.start_new_thread(loop1,()) 运行上面的代码,你会发现loop1方法中的循环打印并没有被调用,而是直接返回异常:
启动的线程中出现未处理的异常
sys.excepthook 丢失
丢失了sys.stderr 这时候你可能会一遍又一遍的检查代码,认为代码错了(没错,那个人就是我)。其实我们的代码本身并没有错。是早期python线程模块的一个缺陷(这个缺陷也是官方不推荐使用这个模块的主要原因) : 当我们在主线程中使用start_new_thread创建新线程时,主线程无法知道什么时候线程结束了,不知道要等多久,导致主线程已经执行完毕,但是子线程还没有完成,所以系统抛出这个异常。
有两种方法可以解决这个异常:
1.让主线程休眠足够长的时间等待子线程返回结果:
导入线程、时间
def循环1():
print "线程数-" + str(thread._count())
我=0
尝试:
当我100:
打印我
时间.睡眠(1)
我=我+1
除了异常e:
打印e
thread.start_new_thread(循环1,())
time.sleep(1000) #让主线程休眠1000秒,足够子线程完成2.锁定线程(早期python线程使用通用处理)
导入线程、时间
def循环1(锁):
print "线程数-" + str(thread._count())
我=0
尝试:
当我100:
打印我
时间.睡眠(1)
我=我+1
除了异常e:
锁.release()
打印e
lock.release() #执行后,释放锁
lock=thread.allocate_lock() #获取锁类型对象
lock.acquire() #锁定
thread.start_new_thread(循环1,(锁,))
while lock.locked(): #等待线程锁释放
上面的pass就是thread模块的普通线程使用。我们可以看到thread模块提供的线程操作极其有限,使用起来非常不灵活。接下来,我们介绍它的同级模块threading。
threading模块(推荐使用)
线程模块是线程的完善。它有一套成熟的线程操作方法,基本上可以完成我们需要的所有线程操作。
常用螺纹加工方法:
threading.currentThread(): 返回当前线程变量。 threading.enumerate(): 返回包含正在运行的线程的列表。运行中是指线程启动后至结束前的状态,不包括启动前和终止后的线程。 threading.activeCount(): 返回正在运行的线程数,其结果与len(threading.enumerate()) 相同。 run(): 用于表示线程活动的方法。 start(): 启动线程活动。 join([time]): 等待线程终止。这会阻塞调用线程,直到线程的join() 方法被调用abort - 正常退出或抛出未处理的异常- 或发生可选的超时。 isAlive(): 返回线程是否处于活动状态。 getName(): 返回线程名称。 setName(): 设置线程名称。在threading模块:中有两种创建线程的方法
1、通过初始化线程对象直接创建:
#编码=utf-8
导入线程、时间
def 测试():
t=threading.currentThread() # 获取当前子线程对象
print t.getName() #打印当前子线程名称
我=0
而i10:
打印我
时间.睡眠(1)
我=我+1
m=threading.Thread(target=test,args=(),name="循环子线程") #初始化一个子线程对象,target为执行的目标函数,args为目标函数的参数,name是子线程的名称
m.start()
t=threading.currentThread() #获取当前线程对象,实际上就是主线程
print t.getName() #打印当前线程的名称,实际上是主线程的名称。可以看到打印结果:
循环子线程
主线程
0
1
2
3
4
5
6
7
82.通过基础线程类创建
导入线程、时间
class myThread (threading.Thread): #创建自定义线程类mythread并继承Thread
def __init__(自身,名称):
"""
重新初始化方法
:param name: 线程名称
"""
super(myThread, self).__init__(name=name)
# self.lock=锁
print "线程名称"+名称
def 运行(自我):
"""
重新运行该方法并在其中写入我们的逻辑
:返回:
"""
我=0
而i10:
打印我
时间.睡眠(1)
我=我+1
如果__name__=="__main__":
t=myThread("mythread")
t.start() 输出:
线程名称线程
0
1
2
3
4
5
6
7
8
9
线程同步
如果两个线程同时访问相同的数据,可能会出现不可预测的结果。这时候就要用到线程同步的概念了。
上面我们讲线程模块的时候,已经用到了线程锁的概念。线程对象的Lock和Rlock可以实现简单的线程同步。这两个对象都有acquire 方法和release 方法。对于那些一次只需要允许一个的人。线程操作的数据可以放在acquire和release方法之间。
下面我们举个例子。我们需要实现三个线程同时访问一个全局变量,并改变这个变量:
1.不加锁的情况
进口螺纹,时间
lock=threading.Lock() #全局锁对象
temp=0 #我们想要多线程访问的全局属性
class myThread (threading.Thread): #创建自定义线程类mythread并继承Thread
def __init__(自身,名称):
"""
重新初始化方法
:param name: 线程名称
"""
super(myThread, self).__init__(name=name)
# self.lock=锁
print "线程名称"+名称
def 运行(自我):
"""
重新运行该方法并在其中写入我们的逻辑
:返回:
"""
全局温度、锁定
我=0
while i2: #这里循环两次,累加全局变量,以增加出错的概率。
temp=temp+1 #子线程中的全局变量加1
print self.name+"--temp=="+str(temp)
我=我+1
如果__name__=="__main__":
t1=myThread("线程1")
t2=myThread("线程2")
t3=myThread("线程3")
#创建三个线程来执行访问
t1.start()
t2.start()
t3.start()执行结果(因为程序运行速度很快,可能多运行几次可能会出现如下结果) : 我们可以发现线程1和线程2同时访问变量,导致印刷中的同等情况
线程名称线程1
线程名称线程2
线程名称线程3
线程1--temp==1 线程2--temp==2
线程1--temp==3
线程2--temp==4
线程3--temp==5
线程3--temp==6
2.加锁情况
导入线程,时间
lock=threading.Lock() #全局锁对象
temp=0 #我们想要多线程访问的全局属性
class myThread (threading.Thread): #创建自定义线程类mythread并继承Thread
def __init__(自身,名称):
"""
重新初始化方法
:param name: 线程名称
"""
super(myThread, self).__init__(name=name)
# self.lock=锁
print "线程名称"+名称
def 运行(自我):
"""
重新运行该方法并在其中写入我们的逻辑
:返回:
"""
全局温度、锁定
if lock.acquire(): #当这里的线程进来访问变量时,锁定该变量
我=0
while i 2: # 循环两次以累积全局变量以增加出错的概率。
temp=temp + 1 # 子线程中的全局变量加1
print self.name + "--temp==" + str(temp)
我=我+1
lock.release() #访问完成后,释放锁以允许其他线程访问
如果__name__=="__main__":
t1=myThread("线程1")
t2=myThread("线程2")
t3=myThread("线程3")
#创建三个线程来执行访问
t1.start()
t2.start()
t3.start()运行结果(无论运行多少次,都不会发生同时访问):
线程名称线程1
线程名称线程2
线程名称线程3
线程1--temp==1
线程1--temp==2
线程2--temp==3
线程2--temp==4
线程3--temp==5
线程3--temp==6 线程同步用在很多地方,比如抢票、抽奖等。我们需要锁定一些资源,以防止多线程访问时出现不可预测的情况。
线程队列
python中的队列使用Queue模块,该模块提供同步且安全的配对顺序,包括FIFO(先进先出)队列Queue、LIFO(后进先出)队列LifoQueue和优先级队列PriorityQueue。这些队列实现了锁原语,可以直接在多线程中使用。队列可以用来实现线程之间的通信
Queue模块:中的常用方法
Queue.qsize() 返回队列的大小Queue.empty() 如果队列为空,则返回True,否则FalseQueue.full() 如果队列已满,则返回True,否则FalseQueue.full 对应队列的maxsize 大小.get([block [, timeout]]) 获取队列,超时等待时间Queue.get_nowait() 相当于Queue.get(False)Queue.put(item) 写入队列,超时等待时间Queue.put_nowait( item) 相当于Queue.put(item, False)Queue.task_done() 完成任务后,Queue.task_done() 函数向任务已完成的队列发送信号。 Queue.join()实际上意味着等待队列为空后再执行其他操作。示例:
标签=["一","拖","三","四","五","六"]
q=Queue.LifoQueue() #先进先出队列
对于标签: 中的t
q.put(t) #将数组数据添加到队列中
对于范围(6): 内的i
print q.get() #检索操作可以放在不同的线程中,不会出现同步问题。结果:
六
五
四
三
【Python编程教程(八):深入多线程与队列应用】相关文章:
2.米颠拜石
3.王羲之临池学书
8.郑板桥轶事十则
用户评论
终于来学习Python多线程了!我一直想在项目中利用它提高效率。
有13位网友表示赞同!
多线程和队列,听起来很有意思,可以做更多更复杂的操作吧?
有17位网友表示赞同!
我曾经尝试过使用Python的并发库,但是总是遇到一些问题。这篇文章能帮到我吗?
有12位网友表示赞同!
之前学习过Java的多线程,希望Python的多线程也能一样简单易用。
有20位网友表示赞同!
感觉学完这篇文章以后,我的Python技能将会更上一层楼!
有8位网友表示赞同!
Python的队列操作是怎么实现的呢?这个系列文章讲解得很深入吧?
有6位网友表示赞同!
想了解多线程和队列之间的关系,这篇文章是个很好的解答机会。
有12位网友表示赞同!
我已经开始实践了,但是遇到了些许困难。希望能在评论区找到答案或建议。
有9位网友表示赞同!
学习Python的多线程知识对于开发大数据项目很有帮助呀!
有11位网友表示赞同!
多线程和队列可以让我同时处理多个任务,真是太棒了!
有18位网友表示赞同!
我很期待学习如何使用Python的threading模块来创建多线程程序。
有6位网友表示赞同!
这篇文章是不是讲的是如何实现高性能的并发编程?
有14位网友表示赞同!
之前一直使用单线程进行开发,现在想要了解一下多线程的优势。
有13位网友表示赞同!
学习Python的多线程能让我写出更流畅高效的代码吗?
有9位网友表示赞同!
Python真是太灵活了!可以用来做各种高级应用开发。
有11位网友表示赞同!
这篇文章绝对是学习Python高级技术的必读之作!
有16位网友表示赞同!
我打算将学习到的知识应用到我的个人项目中,提升项目的效率。
有6位网友表示赞同!
学习新的技术总是充满乐趣和挑战,期待深入了解Python的多线程机制。
有5位网友表示赞同!
非常感谢作者分享这些有用的知识!
有11位网友表示赞同!