python并发编程之多线程

多线程

线程

1.什么是线程

  • 进程是一个执行空间 , 线程就是其中真正工作的单位 , 每一个进程至少有一个线程(如果我们把操作系统比喻为一个工厂 , 进程就是车间 , 线程就是流水线)

进程包含了运行该程序所需要所有资源 , 进程是一个资源单位 , 线程是CPU的最小执行单位

每一个进程一旦被创建 , 就默认开启了一条线程 , 称之为主线程

2.为什么使用线程

  • 多线程指的是,在一个进程中开启多个线程,简单的讲:如果多个任务共用一块地址空间,那么必须在一个进程内开启多个线程。详细的讲分为4点:

    1. 多线程共享一个进程的地址空间

    1. 线程比进程更轻量级,线程比进程更容易创建可撤销,在许多操作系统中,创建一个线程比创建一个进程要快10-100倍,在有大量线程需要动态和快速修改时,这一特性很有用

    1. 若多个线程都是CPU密集型的,那么并不能获得性能上的增强,但是如果存在大量的计算和大量的I/O处理,拥有多个线程允许这些活动彼此重叠运行,从而会加快程序执行的速度。

    1. 在多CPU系统中,为了最大限度的利用多核,可以开启多个线程,比开进程开销要小的多。(这一条并不适用于python)

使用线程可以提高程序效率

为何不用多进程提高效率 : 是因为进程对操作系统的资源耗费非常高

3.线程与进程的区别:

  1. 线程共享创建它的进程的地址空间 ; 进程有自己的地址空间。

  2. 线程可以直接访问其进程的数据段;进程拥有自己父进程数据段的副本。

  3. 线程可以直接与其进程的其他线程通信;进程必须使用进程间通信来与兄弟进程通信。

  4. 新线程很容易创建;新流程需要复制父流程。线程可以对同一进程的线程进行相当大的控制;进程只能控制子进程。对主线程的更改(取消,优先级更改等)可能会影响进程的其他线程的行为;对父进程的更改不会影响子进程。

4.什么时候开启多线程

  • 当程序中遇到IO操作时(当程序中时纯计算任务时 也无法提高效率)

5.如何使用

  • from threading import Thread

创建线程与创建进程的方式几乎一样 , 但是创建子进程会将父进程的资源复制执行一遍 , 所以必须在__main__下执行 , 而创建线程则不一样 , 线程间共享进程资源,所以不需要复制执行父线程代码,所以可以不加__main__

一 . 创建线程的两种方式

  1. 调用类型

from threading import Thread
​
​
def task():print('thread running...')
​
​
if __name__ == '__main__':t = Thread(target=task)t.start()
​print('主线程')
​
# 执行结果
# thread running...  (子线程比主线程执行速度更快)
# 主线程
  1. 继承类型

from threading import Thread
​
​
class Sayhi(Thread):def __init__(self,name):super().__init__()self.name=namedef run(self):print('%s say hello' % self.name)
​
​
if __name__ == '__main__':t = Sayhi('jason')t.start()print('主线程')# 执行结果
#jason say hello
#主线程

 

二 . 线程的常用方法

Thread实例化对象的方法:
# 1.isAlive():      判断线程是否还存在(未终止)
# 2.getName():      返回线程名
# 3.setName():      设置线程名
​
threading模块下提供的方法
# threading.currentThread():        返回当前的线程变量
# threading.enumerate():        返回一个正在运行的线程列表
# threading.activecount():      返回当前运行的线程数量
# len(threading.activecount()):     与上一个方法返回相同值

 

三 . 在一个进程下开启多个线程与在一个进程下开启多个子进程的区别

  1. 开启速度 : 开启线程>>开启进程(所以程序效率会大大提高)

  2. id :

    • 进程开启多线程的pid都相同 ( 很好理解pid是process id , 所以线程pid相同)

    • 进程开启多个进程的pid不同

  3. 空间资源:

    • 进程开启的多线程的共享进程内的资源 , 某线程修改数据后 . 其他线程再访问则是新的数据

    • 进程开启多个子进程的数据互相独立 , 子进程内修改数据不会对其他进程数据造成干扰

 

守护线程

守护线程(setdaemon)

  • 守护线程 : 守护线程会在所有非守护线程结束后结束

    守护线程本质是上是在守护主线程 ,但是对于主线程来说 , 运行完毕指的是主线程所在的进程内所有非守护进程统统运行完毕,主线程才算运行完毕

from threading import Thread
import time
​
def task1():print('sub thread is running...')time.sleep(0.5)print('sub thread end...')
def task2():time.sleep(0.1)print('task2 is run...')
​
t1 = Thread(target=task1)
t2 = Thread(target= task2)
​
t1.setDaemon(True)  # 将t1设置为守护线程, 必须在start之前设置
​
t1.start()
t2.strat()
​
# 执行结果
#sub thread run...
#task2 is run...
​
​

 

线程互斥锁(Lock)

  • 什么时候用锁 :

    当多个进程或多个线程需要同时修改同一份数据时,可能会造成数据错乱,所以必须加锁

import time
from threading import Thread,Lock
​
lock =Lock()  # 实例化锁对象
​
a = 100def task():lock.acquire()  # 给线程上锁global a  # 访问全局atemp = a - 1  # 修改全局atime.sleep(0.01)a = templock.release()   # 释放锁,线程执行完毕
​
ts = []
for i in range(100):t = Thread(target=task)t.start()ts.append(t)
​
for t in ts:  # lock保证了多线程串行,同时主线程print(a)也在其中,但是我们想得到最终结果,所以用join人为设置顺序
    t.join()
​
​
print(a)

信号量(Semaphore)

信号量:

  • 其实也是一种锁 , 特点是可以设置一个数据可以被几个线程(进程)共享.

    与普通锁的区别:

    • 普通锁一旦加锁,则意味着这个数据在同一时间只能被一个线程使用

    • 信号量这种锁,特点是可以设置一个数据可以被几个线程(进程)共享

  • 使用场景

    • 可以限制一个数据同时访问的次数 , 保证程序正常运行

from threading import Thread,Semaphore
import time
sem = Semaphore(3)  # 设置最大访问进程数
​
​
def task():sem.acquire()print('你好啊')time.sleep(3)sem.release()
​
​
for i in range(10):t = Thread(target=task)
​t.start()# 执行结果太长, 就不打印了
# 现象描述 : 就是3个一次打印

守护进程的使用

"""
用生产者消费者模型实现一个顾客吃汉堡的功能
主要是生产者生产处汉堡放入队列,然后消费者吃掉,
要判断什么时候顾客吃完了所有生产了的汉堡
"""
from multiprocessing import Process, JoinableQueue
import time, random
​
def eat_hotdog(name, q):while True:res = q.get()print('%s吃了%s' % (name,res))time.sleep(random.randint(1,2))q.task_done()
​
​
def make_Hotdog(name, q):for i in range(1,6):time.sleep(random.randint(1,2))print('%s生产了第%s个热狗' % (name, i))res = '%s的%s个热狗' % (name,i)q.put(res)
​
​
if __name__ == '__main__':q = JoinableQueue()
​#生产者c1 = Process(target=make_Hotdog, args=('a热狗店', q))c1.start()
​#生产者2c2 = Process(target=make_Hotdog, args=('b热狗店',q))c2.start()
​# 消费者p2 = Process(target=eat_hotdog, args=('顾客',q))p2.daemon = True  # 队列阻塞打开,主进程执行完毕,守护进程死
    p2.start()
​
​# 保证生产者全部完成
    c1.join()c2.join()
​
​# 保证队列中的数据全部被处理了'''join:阻止,直到队列中的所有项目都已获取并处理完毕。
​每当项目添加到队列时,未完成任务的计数就会增加。 每当消费者调用task_done()以指示该项目已被检索并且其上的所有工作都已完成时,计数就会下降。 当未完成任务的数量降至零时,join()取消阻塞。'''q.join()  # JoinableQueue方法

 

转载于:https://www.cnblogs.com/liusijun113/p/10211715.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/449870.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaScript几个难点

1. 立即执行函数 立即执行函数,即Immediately Invoked Function Expression (IIFE),正如它的名字,就是创建函数的同时立即执行。它没有绑定任何事件,也无需等待任何异步操作: (function() { // 代码 // ...})(); f…

真格量化学习

真格量化学习使用 期权的量化回测 引入必须的库: from PoboAPI import * import datetime import time import numpy as np初始化参数设定 以50为例 def OnStart(context) :print("I\m starting...")#设定一个全局变量品种,本策略交易50ETF期权g

智能小程序档案馆——如何给“包”瘦身

上传小程序代码的时候包体积太大不知如何是好?小程序打开速度慢,流量耗费大不知如何优化?在今天的文章里,我们一起来讨论一下如何给“包”瘦身。 为什么要限制包的大小? 我们都知道小程序作为一种 Hybrid 的解决方案&a…

软件架构师的能力与特质

软件开发工程师的职业发展无非两大类:一是做“官”,从事管理工作;二则继续从事技术工作。对于后者,软件架构师(software architect)是很多软件开发工程师追求的理想岗位。在这我想谈一谈软件架构师所需的几…

IntelliJ IDEA编码设置

见:https://www.cnblogs.com/winner-0715/p/6364306.html项目中为了避免乱码等问题应该使用UTF-8编码方式,其实把编码方式设置成UTF-8是创建完项目后就要做的事,按照如图所示进行设置:这里要将Transparent native-to-ascii conversion选项勾选, 否则项目…

C#实现像微信PC版一样的扫码登录功能

现在好些网站都支持扫码登录,感觉上安全了很多,但是本地程序扫码登录的不多,就用C#实现了一下,需要作如下准备 在官网上申请一个企业微信,有条件的话做个企业认证吧,我们的是认证过的,所以账号和本地其他系统的账号是统一的.在应用中创建一个应用,这个是关键,我们扫码就是和它有…

JVM(一)史上最佳入门指南

2019独角兽企业重金招聘Python工程师标准>>> 提到Java虚拟机(JVM),可能大部分人的第一印象是“难”,但当让我们真正走入“JVM世界”的时候,会发现其实问题并不像我们想象中的那么复杂。唯一真正令我们恐惧的…

如何成为一个技术“牛人”

今天给浙江大学过来的几个还没有毕业的研究生做面试,这些研究生是想来公司实习的。在面试的过程中,一个学生问我“我们有C/C、JAVA等等多种语言,我如何才能成为某一方面的一个技术牛人呢?这一问题一直困扰着我”,对于这…

python量化数据处理小细节(以后还会不断补充)

使用tushare数据源获取数据后处理 以下都是本人在获得数据后,进行量化回测时,处理数据遇到的各种坑以及解决方案,有些甚至都很幼稚,切勿嘲笑 获取数据 导包 import tushare as ts import pandas as pd import matplotlib #(ju…

Linux find和grep的区别

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 grep是查找文件中匹配条件的行,find是搜索匹配条件的文件。 1.find:查找文件或目录语法: find 查找位置 文件名或目录名如:在…

Mysql 忘记密码重置教程

https://jingyan.baidu.com/article/454316ab4e9e65f7a7c03ad1.html 百度经验转载于:https://www.cnblogs.com/leaf-cq/p/10410694.html

067:【Django数据库】ORM查询条件详解-range

【Django数据库】ORM查询条件详解-range range:判断某个 field 的值是否在给定的区间中。示例代码如下: # views.py文件内容:from datetime import datetime from django.utils.timezone import make_awaredef index(request):start_time ma…

贴吧爬虫

import requests import re#根据url获取网页html内容 def getHtmlContent(url):page requests.get(url)return page.texthtml getHtmlContent(https://tieba.baidu.com/p/4840106397)#以html中使用re模块解析出所有jpg图片的url #百度贴吧html中jpg图片的url格式:…

别把自己变成了“二等公民”

上周参加一个代码审查会,在会上发现了设计上的一个很严重的错误。于是,我提了好几个问题,想知道为什么会出现这一错误。但是,我的同事告诉我这都是印度团队做的设计。需要提供的一个背景信息是,这个项目是我所在的研发…

jquery函数加载及生成随机数

$(document).ready(function () {var code ; //在全局定义验证码  1.将函数写好 function createCode(){code "";var codeLength 4;//验证码的长度var checkCode document.getElementById("code");var random new Array(0,1,2,3,4,5,6,7,8,9,A,B,C…

rsync解说

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 一、简介1、认识Rsync(remote synchronize)是一个远程数据同步工具,可通过LAN/WAN快速同步多台主机间…

关于java中getClass()和getSuperClass()的讲解

为了讲解这个问题,我们先来看一下下面的代码: package com.yonyou.test;import java.util.Date;class Test extends Date{private static final long serialVersionUID 1L;public static void main(String[] args) {new Test().print();}public void print(){Syste…

期权回测框架设计思路

期权回测,博主已经研究了很长时间,也接触了不少平台,如真格,以及这位博主提供的思路(https://blog.csdn.net/luoqingyong/article/details/107523930),利用backtrader进行期权回测。确实国内做期…

UVA815

这道题主要学到的就是数据结构的组织,一些需要从小到大排列的东西,这些东西还有对应的东西。这个时候使用map可以解决 下面贴出代码。其中所使用的思想,估计这个东西是没法学的,这就只能是灵感 //这是什么吉尔题,题意都…

我对应聘者的面试原则

最近参与了几次单位招聘面试工作,在面试工程师时,我是用我的分层准则指导与候选人的交流内容,以确定他的能力层次是否达到我所期望的。大体上软件工程师可以分为三大层次,分别是技术知识积累层、掌握设计方法层以及运用开发方法论…