在实际处理数据时,因系统内存有限,我们不可能一次把所有数据都导出进行操作,所以需要批量导出依次操作.为了加快运行,我们会采用多线程的方法进行数据处理, 以下为我总结的多线程批量处理数据的模板:
主要分为三大部分:
先为大家介绍线程的相关概念:
在飞车程序中,如果没有多线程,我们就不能一边听歌一边玩飞车,听歌与玩 游戏 不能并行;在使用多线程后,我们就可以在玩 游戏 的同时听背景音乐.在这个例子中启动飞车程序就是一个进程,玩 游戏 和听音乐是两个线程.
Python 提供了 threading 模块来实现多线程:
因为新建线程系统需要分配资源、终止线程系统需要回收资源,所以如果可以重用线程,则可以减去新建/终止的开销以提升性能.同时,使用线程池的语法比自己新建线程执行线程更加简洁.
Python 为我们提供了 ThreadPoolExecutor 来实现线程池,此线程池默认子线程守护.它的适应场景为突发性大量请求或需要大量线程完成任务,但实际任务处理时间较短.
其中 max_workers 为线程池中的线程个数,常用的遍历方法有 map 和 submit+as_completed .根据业务场景的不同,若我们需要输出结果按遍历顺序返回,我们就用 map 方法,若想谁先完成就返回谁,我们就用 submit+as_complete 方法.
我们把一个时间段内只允许一个线程使用的资源称为临界资源,对临界资源的访问,必须互斥的进行.互斥,也称间接制约关系.线程互斥指当一个线程访问某临界资源时,另一个想要访问该临界资源的线程必须等待.当前访问临界资源的线程访问结束,释放该资源之后,另一个线程才能去访问临界资源.锁的功能就是实现线程互斥.
我把线程互斥比作厕所包间上大号的过程,因为包间里只有一个坑,所以只允许一个人进行大号.当第一个人要上厕所时,会将门上上锁,这时如果第二个人也想大号,那就必须等第一个人上完,将锁解开后才能进行,在这期间第二个人就只能在门外等着.这个过程与代码中使用锁的原理如出一辙,这里的坑就是临界资源. Python 的 threading 模块引入了锁. threading 模块提供了 Lock 类,它有如下方法加锁和释放锁:
我们会发现这个程序只会打印"第一道锁",而且程序既没有终止,也没有继续运行.这是因为 Lock 锁在同一线程内第一次加锁之后还没有释放时,就进行了第二次 acquire 请求,导致无法执行 release ,所以锁永远无法释放,这就是死锁.如果我们使用 RLock 就能正常运行,不会发生死锁的状态.
在主线程中定义 Lock 锁,然后上锁,再创建一个子 线程t 运行 main 函数释放锁,结果正常输出,说明主线程上的锁,可由子线程解锁.
如果把上面的锁改为 RLock 则报错.在实际中设计程序时,我们会将每个功能分别封装成一个函数,每个函数中都可能会有临界区域,所以就需要用到 RLock .
一句话总结就是 Lock 不能套娃, RLock 可以套娃; Lock 可以由其他线程中的锁进行操作, RLock 只能由本线程进行操作.
进程的概念:以一个整体的形式暴露给操作系统管理,里面包含各种资源的调用. 对各种资源管理的集合就可以称为进程.
线程的概念:是操作系统能够进行运算调度的最小单位.本质上就是一串指令的集合.
进程和线程的区别:
①.、线程共享内存空间,进程有独立的内存空间.
此时此刻呢这个程序,吸取了上面这个程序的缺点,创建了一个列表,把所有的线程实例都存进去,然后使用一个for循环依次对线程实例调用join方法,这样就可以使得主线程等待所创建的所有子线程执行完毕才能往下走. 注意实验结果:和两个线程的结果都是两秒多一点
注意观察实验结果,并没有执行打印task has done,并且程序执行时间极其短.
这是因为在主线程启动子线程前把子线程设置为守护线程.
只要主线程执行完毕,不管子线程是否执行完毕,就结束.但是会等待非守护线程执行完毕
主线程退出,守护线程全部强制退出.皇帝死了,仆人也跟着殉葬
应用的场景 : socket-server
下面这个程序是一个典型的生产者消费者模型.
生产者消费者模型是经典的在开发架构中使用的模型
运维中的集群就是生产者消费者模型,生活中很多都是
那么,多线程的使用场景是什么?
python中的多线程实质上是对上下文的不断切换,可以说是假的多线程.而我们知道,io操作不占用cpu,计算占用cpu,那么python的多线程适合io操作密集的任务,比如socket-server,那么cpu密集型的任务,python怎么处理?python可以折中的利用计算机的多核:启动八个进程,每个进程有一个线程.这样就可以利用多进程解决多核问题.
线程也就是轻量级的进程,多线程允许一次执行多个线程,Python是多线程语言,它有一个多线程包,GIL也就是全局解释器锁,以确保一次执行单个线程,一个线程保存GIL并在将其传递给下一个线程之前执行一些操作,也就产生了并行执行的错觉.
多线程能让你像运行一个独立的程序一样运行一段长代码.这有点像调用子进程(subprocess),不过区别是你调用shu的是一个函数或者一个类,而不是独立的程序.
程基本上是一个独立执行流程.单个进程可以由多个线程组成.程序中的每个线程都执行特定的任务.例如,当你在电脑上玩游戏时,比如说国际足联,整个游戏是一个单一的过程.,但它由几个线程组成,负责播放音乐、接收用户的输入、同步运行对手等.所有这些都是单独的线程,负责在同一个程序中执行这些不同的任务.
每个进程都有一个始终在运行的线程.这是主线.这个主线程实际上创建子线程对象.子线程也由主线程启动.
有很多的场景中的事情是同时进行的,比如开车的时候,手和脚共同来驾驶汽车,再比如唱歌跳舞也是同时进行的
结果:
_thread
threading(推荐使用)
threading.enumerate() 可查看当前正在运行的线程
结果: 出现资源竞争导致计算结果不正确
(1)当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制
结果: 计算正确
结果:卡住了
在线程间共享多个资源的时候,如果两个线程分别战友一部分资源且同时等待对方资源,就会造成死锁
(1)程序设计时避免(银行家算法)
以上就是土嘎嘎小编为大家整理的python+函数多线程相关主题介绍,如果您觉得小编更新的文章只要能对粉丝们有用,就是我们最大的鼓励和动力,不要忘记讲本站分享给您身边的朋友哦!!