欢迎来真孝善网,为您提供真孝善正能量书籍故事!

Python编程教程(八):深入多线程与队列应用

时间:10-28 名人轶事 提交错误

大家好,今天来为大家分享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多线程了!我一直想在项目中利用它提高效率。

    有13位网友表示赞同!

相知相惜

多线程和队列,听起来很有意思,可以做更多更复杂的操作吧?

    有17位网友表示赞同!

繁华若梦

我曾经尝试过使用Python的并发库,但是总是遇到一些问题。这篇文章能帮到我吗?

    有12位网友表示赞同!

風景綫つ

之前学习过Java的多线程,希望Python的多线程也能一样简单易用。

    有20位网友表示赞同!

揉乱头发

感觉学完这篇文章以后,我的Python技能将会更上一层楼!

    有8位网友表示赞同!

﹏櫻之舞﹏

Python的队列操作是怎么实现的呢?这个系列文章讲解得很深入吧?

    有6位网友表示赞同!

涐们的幸福像流星丶

想了解多线程和队列之间的关系,这篇文章是个很好的解答机会。

    有12位网友表示赞同!

爱你心口难开

我已经开始实践了,但是遇到了些许困难。希望能在评论区找到答案或建议。

    有9位网友表示赞同!

冷眼旁观i

学习Python的多线程知识对于开发大数据项目很有帮助呀!

    有11位网友表示赞同!

▼遗忘那段似水年华

多线程和队列可以让我同时处理多个任务,真是太棒了!

    有18位网友表示赞同!

逃避

我很期待学习如何使用Python的threading模块来创建多线程程序。

    有6位网友表示赞同!

墨染年华

这篇文章是不是讲的是如何实现高性能的并发编程?

    有14位网友表示赞同!

残留の笑颜

之前一直使用单线程进行开发,现在想要了解一下多线程的优势。

    有13位网友表示赞同!

念初

学习Python的多线程能让我写出更流畅高效的代码吗?

    有9位网友表示赞同!

白恍

Python真是太灵活了!可以用来做各种高级应用开发。

    有11位网友表示赞同!

|赤;焰﹏゛

这篇文章绝对是学习Python高级技术的必读之作!

    有16位网友表示赞同!

她最好i

我打算将学习到的知识应用到我的个人项目中,提升项目的效率。

    有6位网友表示赞同!

像从了良

学习新的技术总是充满乐趣和挑战,期待深入了解Python的多线程机制。

    有5位网友表示赞同!

堕落爱人!

非常感谢作者分享这些有用的知识!

    有11位网友表示赞同!

【Python编程教程(八):深入多线程与队列应用】相关文章:

1.蛤蟆讨媳妇【哈尼族民间故事】

2.米颠拜石

3.王羲之临池学书

4.清代敢于创新的“浓墨宰相”——刘墉

5.“巧取豪夺”的由来--米芾逸事

6.荒唐洁癖 惜砚如身(米芾逸事)

7.拜石为兄--米芾逸事

8.郑板桥轶事十则

9.王献之被公主抢亲后的悲惨人生

10.史上真实张三丰:在棺材中竟神奇复活