Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元。

1.1、threading模块

threading模块建立在_thread模块之上。thread模块以低级=原始的方式来处理和控制线程,而threading模块
通过对thread进行二次封装,提供了更方便的api来处理线程。

简单的线程实例:
创建了20个“前台”线程,然后控制器就交给了CPU,CPU根据指定算法进行调度,分片执行指令

 #!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
创建一个简单的threading线程实例
"""
import threading
import time def to_worker(num):
"""
线程方法
:param num:
:return:
"""
time.sleep(1)
print("The num is %s" % num)
return for i in range(5):
t = threading.Thread(target=to_worker, args=(i, ))
t.start() #激活线程

代码执行结果:

1.2、创建线程的构造方法

t = threading.Thread(group = None, target = None, name = Nome, args = 0, kwargs = {})

注释说明:
group --线程组
target --要执行的方法
name --线程名
args/kwargs -要传入方法的参数

Thread类提供了以下方法:
1、t.start() --激活线程
2、t.getName() --获取线程的名称
3、t.setName() --设置线程的名称
4、t.name() --获取或设置线程的名称
5、t.is_alive() --判断线程是否为激活状态
6、t.isAlive() --判断线程是否为激活状态
7、t.setDaemon() --设置为后台线程或前台线程(默认:False)
8、t.isDaemon() --判断是否为守护线程
9、t.ident() --获取线程的标识符。线程标识符是一个非零整数,只有在调用start()方法后,该属性才有效,否则它只返回None
10、t.join() --逐个执行每个线程,执行完毕后继续往下执行,该方法使得多线程变得无意义。
11、t.run() --线程被cpu调度后自动执行线程对象的run方法

1.3、python线程锁

当有一个数据有多个线程对其进行修改的时候,任何一个线程改变他都会对其他线程造成影响,如果我们想某一个线程在使用完之前,其他线程不能对其修改,就需要对这个线程加一个线程锁。

简单的线程锁实例:

 #!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
线程锁小实例
"""
import threading
import time globals_num = 0 lock = threading.RLock() def Func():
lock.acquire() #获取锁
global globals_num
globals_num += 1
time.sleep(1)
print(globals_num)
lock.release() #释放锁 for i in range(10):
t = threading.Thread(target=Func)
t.start()

代码执行结果:

threading.RLock和threading.Lock 的区别
RLock允许在同一线程中被多次acquire。而Lock却不允许这种情况。 如果使用RLock,那么acquire和release必须成对出现,即调用了n次acquire,必须调用n次的release才能真正释放所占用的琐。

 import threading
lock = threading.Lock() #Lock对象
lock.acquire()
lock.acquire() #产生了死琐。
lock.release()
lock.release()  import threading
rLock = threading.RLock() #RLock对象
rLock.acquire()
rLock.acquire() #在同一线程内,程序不会堵塞。
rLock.release()
rLock.release()

1.4、threading.Event

1、python线程的事件用于主线程控制其他线程的执行,事件主要提供了三个方法:set、wait、clear。
2、事件处理的机制:全局定义了一个Flag,如果Flag值为False,那么当程序执行event.wait方法时就会阻塞,
如果Flag值为True,那么event.wait方法时便不再阻塞。

方法说明:
clear --将Flag设置为False
set -- 将Flag设置为True
Event.isSet() --判断标识符是否为True

threading.Event简单实例:
当线程执行的时候,如果flag为False,则线程会阻塞,当flag为True的时候,线程不会阻塞。它提供了本地和远程的并发性。

 #!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
threading.Event事件实例
"""
import threading def do(event):
print("start.....")
event.wait()
print("execuse...") event_obj = threading.Event() for i in range(5):
t = threading.Thread(target=do, args=(event_obj,))
t.start() event_obj.clear()
inp = input('input:(true) ')
if inp == "true":
event_obj.set()

代码执行结果:

1.5、threading.Condition(条件变量)

示例说明:当小伙伴a在往火锅里面添加鱼丸,这个就是生产者行为;另外一个小伙伴b在吃掉鱼丸就是消费者行为。当火锅里面鱼丸达到一定数量加满后b才能吃,这就是一种条件判断了。

Condition(条件变量)通常与一个锁关联。需要在多个Contidion中共享一个锁时,可以传递一个Lock/RLock实例给构造方法,否则它将自己生成一个RLock实例。

可以认为,除了Lock带有的锁定池外,Condition还包含一个等待池,池中的线程处于状态图中的等待阻塞状态,直到另一个线程调用notify()/notifyAll()通知;得到通知后线程进入锁定池等待锁定。

Condition():

acquire(): 线程锁
release(): 释放锁
wait(timeout): 线程挂起,直到收到一个notify通知或者超时(可选的,浮点数,单位是秒s)才会被唤醒继续运行。wait()必须在已获得Lock前提下才能调用,否则会触发RuntimeError。
notify(n=1): 通知其他线程,那些挂起的线程接到这个通知之后会开始运行,默认是通知一个正等待该condition的线程,最多则唤醒n个等待的线程。notify()必须在已获得Lock前提下才能调用,否则会触发RuntimeError。notify()不会主动释放Lock。
notifyAll(): 如果wait状态线程比较多,notifyAll的作用就是通知所有线程。

生产者与消费者示例:
现实场景:当a同学王火锅里面添加鱼丸加满后(最多3个,加满后通知b去吃掉),通知b同学去吃掉鱼丸(吃到0的时候通知a同学继续添加)

 #!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
threading.Condition
"""
import threading
import time con = threading.Condition() num = 0 #生产者
class Producer(threading.Thread): def __init__(self):
threading.Thread.__init__(self) def run(self):
#锁定线程
global num
con.acquire() #获取锁
while True:
print("a同学开始添加......")
num += 1
print("锅里丸子个数为:%s" % str(num))
time.sleep(1)
if num >= 3:
print("丸子个数已经达到3个了,无法添加。")
#唤醒等待的线程
con.notify() #唤醒同学开吃
#等待通知
con.wait() #释放锁
con.release() #消费者
class Consumers(threading.Thread):
def __init__(self):
threading.Thread.__init__(self) def run(self):
con.acquire()
global num
while True:
print("我准备开吃了...")
num -= 1
print("锅里丸子数量为:%s" % str(num))
time.sleep(2)
if num <= 0:
print("丸子吃完了,赶紧添加啦..")
con.notify() #唤醒等待的线程
#等待通知
con.wait()
con.release() #释放锁 p = Producer()
c = Consumers()
p.start()
c.start()

代码执行结果:

1.6、Queue模块

1.6.1、创建一个“队列”对象
import queue
q = queue.queue(maxsize = 10)
queue.queue类即是一个队列的同步实现。队列长度可为无限或者有限。可通过queue的构造函数的可选参数maxsize来设定队列长度。如果maxsize小于1就表示队列长度无限。

1.6.2、将一个值放入队列中
q.put(10)
调用队列对象的put()方法在队尾插入一个项目。put()有两个参数,第一个item为必需的,为插入项目的值;第二个block为可选参数,默认为
1。如果队列当前为空且block为1,put()方法就使调用线程暂停,直到空出一个数据单元。如果block为0,put方法将引发Full异常。

1.6.3、将一个值从队列中取出
q.get()
调用队列对象的get()方法从队头删除并返回一个项目。可选参数为block,默认为True。如果队列为空且block为True,get()就使调用线程暂停,直至有项目可用。如果队列为空且block为False,队列将引发Empty异常。

1.6.4、Python queue模块有三种队列及构造函数:
1、Python queue模块的FIFO队列先进先出。 class queue.queue(maxsize)
2、LIFO类似于堆,即先进后出。 class queue.Lifoqueue(maxsize)
3、还有一种是优先级队列级别越低越先出来。 class queue.Priorityqueue(maxsize)

1.6.5、queue常用方法(q =queue.queue()):
q.qsize() 返回队列的大小
q.empty() 如果队列为空,返回True,反之False
q.full() 如果队列满了,返回True,反之False
q.full 与 maxsize 大小对应
q.get([block[, timeout]]) 获取队列,timeout等待时间
q.get_nowait() 相当q.get(False)
非阻塞 q.put(item) 写入队列,timeout等待时间
q.put_nowait(item) 相当q.put(item, False)
q.task_done() 在完成一项工作之后,q.task_done() 函数向任务已经完成的队列发送一个信号
q.join() 实际上意味着等到队列为空,再执行别的操作

1.6.6、简单的queue实例:生产者-消费者模型

 #!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Queue队列
"""
import queue
import threading message = queue.Queue(10) def producer(i):
while True:
message.put(i) def consumer(i):
while True:
msg = message.get(i) for i in range(12):
t = threading.Thread(target=producer, args=(i, ))
t.start()
for i in range(10):
t = threading.Thread(target=consumer, args=(i, ))
t.start()

1.7、自定义线程池

1.7.1、方法一:简单往队列中传输线程数

 #!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
自定义线程池
方法一:简单往队列中传输线程数
"""
import threading
import time
import queue class ThreadingPool():
def __init__(self, max_num = 10):
self.queue = queue.Queue(max_num)
for i in range(max_num):
self.queue.put(threading.Thread) def getthreading(self):
return self.queue.get() def addthreading(self):
self.queue.put(threading.Thread) def func(p, i):
time.sleep(1)
print(i)
p.addthreading() if __name__ == "__main__":
p = ThreadingPool()
for i in range(12):
thread = p.getthreading()
t = thread(target = func, args = (p, i))
t.start()

代码执行结果:

1.7.2、方法二:往队列中无限添加任务

 #!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
自定义线程池
方法二:往队列中无限添加任务
"""
import queue
import threading
import contextlib
import time StopEvent = object() class ThreadPool(object): def __init__(self, max_num):
self.q = queue.Queue()
self.max_num = max_num self.treminal = False
self.generate_list = []
self.free_list = [] def run(self, func, args, callback=None):
"""
线程池执行一个任务
:param func: 任务函数
:param args: 任务函数所需参数
:param callback: 任务执行失败或成功后执行的回调函数,回调函数有两个参数:1、任务函数执行状态;2、任务函数返回值(默认为None,即不执行回调函数)
:return:如果线程池已经终止,则返回True,否则为None
"""
if len(self.free_list) == 0 and len(self.generate_list) < self.max_num:
self.generate_thread()
w = (func, args, callback,)
self.q.put(w) def generate_thread(self):
"""
创建一个线程
:param self:
:return:
"""
t = threading.Thread(target=self.call)
t.start() def call(self):
"""
循环去获取任务函数并执行任务函数
:return:
"""
current_thread = threading.currentThread
self.generate_list.append(current_thread) event = self.q.get() #获取线程
while event != StopEvent: #判断获取的线程数不等于全局变量
func, arguments, callback = event #拆分元组, 获取执行函数,参数, 回调函数
try:
result = func(*arguments) #执行函数
status = True except Exception as e: #函数执行失败
status = False
result = e if callback is not None:
try:
callback(status, result)
except Exception as e:
pass with self.work_state():
event = self.q.get() else:
self.generate_list.remove(current_thread) def close(self):
"""
关闭线程,给传输全局非元组的变量来进行关闭
:return:
"""
for i in range(len(self.generate_list)):
self.q.put(StopEvent) def terminate(self):
"""
突然关闭线程
:return:
"""
self.terminal = True
while self.generate_list:
self.q.put(StopEvent)
self.q.empty() def work_state(self):
self.free_list.append(threading.current_thread)
try:
yield
finally:
self.free_list.remove(threading.currentThread) def work(i):
print(i)
return i + 1 #返回给回调函数 def callback(ret):
print(ret) pool = ThreadPool(10)
for item in range(50):
pool.run(func=work, args=(item, ), callback=callback) pool.terminate()

python--线程知识详解的更多相关文章

  1. Python基础知识详解 从入门到精通(七)类与对象

    本篇主要是介绍python,内容可先看目录其他基础知识详解,欢迎查看本人的其他文章Python基础知识详解 从入门到精通(一)介绍Python基础知识详解 从入门到精通(二)基础Python基础知识详 ...

  2. Python字符串切片操作知识详解

    Python字符串切片操作知识详解 这篇文章主要介绍了Python中字符串切片操作 的相关资料,需要的朋友可以参考下 一:取字符串中第几个字符 print "Hello"[0] 表 ...

  3. Python开发技术详解PDF

    Python开发技术详解(高清版)PDF 百度网盘 链接:https://pan.baidu.com/s/1F5J9mFfHKgwhkC5KuPd0Pw 提取码:xxy3 复制这段内容后打开百度网盘手 ...

  4. RabbitMQ,Apache的ActiveMQ,阿里RocketMQ,Kafka,ZeroMQ,MetaMQ,Redis也可实现消息队列,RabbitMQ的应用场景以及基本原理介绍,RabbitMQ基础知识详解,RabbitMQ布曙

    消息队列及常见消息队列介绍 2017-10-10 09:35操作系统/客户端/人脸识别 一.消息队列(MQ)概述 消息队列(Message Queue),是分布式系统中重要的组件,其通用的使用场景可以 ...

  5. 《python开发技术详解》|百度网盘免费下载|Python开发入门篇

    <python开发技术详解>|百度网盘免费下载|Python开发入门篇 提取码:2sby  内容简介 Python是目前最流行的动态脚本语言之一.本书共27章,由浅入深.全面系统地介绍了利 ...

  6. python time模块详解

    python time模块详解 转自:http://blog.csdn.net/kiki113/article/details/4033017 python 的内嵌time模板翻译及说明  一.简介 ...

  7. 【python进阶】详解元类及其应用2

    前言 在上一篇文章[python进阶]详解元类及其应用1中,我们提到了关于元类的一些前置知识,介绍了类对象,动态创建类,使用type创建类,这一节我们将继续接着上文来讲~~~ 5.使⽤type创建带有 ...

  8. Python环境搭建详解(Window平台)

    前言 Python,是一种面向对象的解释型计算机程序设计语言,是纯粹的自由软件,Python语法简洁清晰,特色是强制用空白符作为语句缩进,具有丰富和强大的库,它常被称为胶水语言. Python是一种解 ...

  9. Java性能分析之线程栈详解与性能分析

    Java性能分析之线程栈详解 Java性能分析迈不过去的一个关键点是线程栈,新的性能班级也讲到了JVM这一块,所以本篇文章对线程栈进行基础知识普及以及如何对线程栈进行性能分析. 基本概念 线程堆栈也称 ...

  10. (转)python collections模块详解

    python collections模块详解 原文:http://www.cnblogs.com/dahu-daqing/p/7040490.html 1.模块简介 collections包含了一些特 ...

随机推荐

  1. SpringBoot的ApplicationRunner

    Article1 在开发中可能会有这样的情景.需要在容器启动的时候执行一些内容.比如读取配置文件,数据库连接之类的.SpringBoot给我们提供了两个接口来帮助我们实现这种需求.这两个接口分别为Co ...

  2. windows 7输入regedit 打不开注册表

    Win 10 win 7 Win7 regedit 打不开 怎么打不开 打不开了怎么办 没反应 不能打开 注册表? 1.使用键盘快捷键 win+r,打开运行工具. 2.在输入框内输入gepedit.m ...

  3. jar解压后重新打包

    因为一些原因修改了jar中的配置文件,但用WinRAR压缩成zip文件后该后缀名为jar,发现重新压缩的文件不可用,所有这些情况下我们必须用jar重新打包. 配置Java环境,让jar命令可用: ja ...

  4. SpringBoot+EventBus使用教程(二)

    简介 继续上篇,本篇文章介绍如何集成spring-boot-starter-guava-eventbus使用EventBus,最新的版本好像已经不叫spring-boot-starter-guava- ...

  5. 是的 你没看错!!!用JAVA为MCU开发物联网程序?

      是的 你没看错!!!用JAVA为MCU开发物联网程序?          一直以来,物联网设备这种嵌入式硬件,对于Java软件开发者来说,就是Black Magic Box,什么中断.寄存器,什么 ...

  6. 【More Effective C++ 条款2】最好使用C++转型操作符

    C的转型方式存在以下两个缺点: 1)几乎允许你将任何类型转化为任何类型,不能精确的指明转型意图,这样很不安全 如将一个pointer-to-base-class-object转型为一个pointer- ...

  7. javascript参数化拼接字符串两种方法

    javascript如果直接使用字符串+的话,会被大量单引号搞晕,可以有两种比较简单的方法使用参数化拼接. 方式一,传统js //示例:StringFormat("abc{0}def&quo ...

  8. 【BZOJ3328】PYXFIB(单位根反演,矩阵快速幂)

    [BZOJ3328]PYXFIB(单位根反演,矩阵快速幂) 题面 BZOJ 题解 首先要求的式子是:\(\displaystyle \sum_{i=0}^n [k|i]{n\choose i}f_i\ ...

  9. Python学习笔记之使用 python -m SimpleHTTPServer 快速搭建http服务

    0x00 概述 搭建FTP,或者是搭建网络文件系统,这些方法都能够实现Linux的目录共享.但是FTP和网络文件系统的功能都过于强大,因此它们都有一些不够方便的地方.比如你想快速共享Linux系统的某 ...

  10. WPF 精修篇 事件触发器

    原文:WPF 精修篇 事件触发器 事件触发器 一般使用的就是动画 <Grid> <TextBlock Text="事件触发器" Opacity="0.2 ...