Python并发编程04 /多线程、生产消费者模型、线程进程对比、线程的方法、线程join、守护线程、线程互斥锁

1. 生产消费者模型

  • 定义:编程思想,模型,设计模式,理论等等,都是一种编程的方法,遇到类似的情况,套用即可.

  • 生产者消费者模型三要素:

    生产者: 产生数据的

    消费者: 接收数据做进一步处理的

    容器: 队列,起到缓冲的作用,平衡生产力与消费力,解耦.

  • 代码示例:

    from multiprocessing import Process
    from multiprocessing import Queue
    import time
    import random def producer(q,name):
    for i in range(1,6):
    time.sleep(random.randint(1,2))
    res = f'{i}号包子'
    q.put(res)
    print(f'生产者{name} 生产了{res}') def consumer(q,name):
    while 1:
    try:
    food = q.get(timeout=3)
    time.sleep(random.randint(1, 3))
    print(f'\033[31;0m消费者{name} 吃了{food}\033[0m')
    except Exception:
    return if __name__ == '__main__':
    q = Queue()
    p1 = Process(target=producer,args=(q,'张三'))
    p2 = Process(target=consumer,args=(q,'李四'))
    p1.start()
    p2.start()

2. 线程的理论知识

  • 什么是线程

    标准描述开启一个进程:开启一个进程:进程会在内存中开辟一个进程空间,将主进程的资料数据全部复制一份,线程会执行里面的代码.

    ***进程是资源单位, 线程是执行单位;是操作系统调度的最小单元,是进程中的实际运作单位.

  • 线程vs进程

    1. 开启进程的开销非常大,比开启线程的开销大很多.
    2. 开启线程的速度非常快.要快几十倍到上百倍.
    3. 同一进程内线程与线程之间可以共享数据,进程与进程之间需借助队列等方法实现通信.
  • 线程的应用

    单个进程开启三个线程.并发的执行任务.

    并发:一个cpu 看起来像是同时执行多个任务.

  • 主线程子线程没有地位之分

    一个主线程在干活,当干完活了,得等待其他线程干完活之后,才能结束本进程.

3. 开启线程的两种方式

  • 方式一

    from threading import Thread
    import time def task(name):
    print(f'{name} is running')
    time.sleep(1)
    print(f'{name} is gone') if __name__ == '__main__': t1 = Thread(target=task,args=('张三',)) # args的参数一定要是元组
    t1.start()
    print('===主线程') # 线程是没有主次之分的.
  • 方式二

    from threading import Thread
    import time class MyThread(Thread):
    def __init__(self,name,l1,s1):
    super().__init__()
    self.name = name
    self.l1 = l1
    self.s1 = s1
    def run(self):
    print(f'{self.name} is running')
    time.sleep(1)
    print(f'{self.name} is gone') if __name__ == '__main__':
    t1 = MyThread('张三', [1,2,3], '180')
    t1.start()
    print('=====主线程')

4. 线程、进程对比代码验证

  • 开启速度对比

    # 多进程
    from threading import Thread
    from multiprocessing import Process
    import os def work():
    print('hello') if __name__ == '__main__':
    t=Process(target=work)
    t.start()
    print('主线程/主进程') # 多线程
    from threading import Thread
    import time def task(name):
    print(f'{name} is running')
    time.sleep(1)
    print(f'{name} is gone') if __name__ == '__main__':
    t1 = Thread(target=task,args=('张三',))
    t1.start()
    print('===主线程') # 结论:
    # 多进程是先打印的'主线程/主进程',多线程是先打印的'张三 is running',所以得出线程的开启速度比进程快
  • 对比pid

    # 多进程
    from multiprocessing import Process
    import time
    import os def task(name):
    print(f'子进程: {os.getpid()}')
    print(f'主进程: {os.getppid()}') if __name__ == '__main__':
    p1 = Process(target=task,args=('张三',)) # 创建一个进程对象
    p2 = Process(target=task,args=('李四',)) # 创建一个进程对象
    p1.start()
    p2.start()
    print(f'==主{os.getpid()}') # 多线程
    from threading import Thread
    import os def task():
    print(os.getpid()) if __name__ == '__main__':
    t1 = Thread(target=task)
    t2 = Thread(target=task)
    t1.start()
    t2.start()
    print(f'===主线程{os.getpid()}') # 结论:
    # 线程没有pid,进程才有pid
  • 共享数据的对比,同一个进程内线程共享内部数据

    from threading import Thread
    import os x = 3
    def task():
    global x
    x = 100 if __name__ == '__main__':
    t1 = Thread(target=task)
    t1.start()
    t1.join()
    print(f'===主线程{x}') # 同一进程内的资源数据对于这个进程内的多个线程来说是共享的.

5. 线程的其他方法

  • 代码示例:

    from threading import Thread
    from threading import currentThread
    from threading import enumerate
    from threading import activeCount
    import os
    import time def task():
    print(currentThread()) # 获取当前线程对象
    time.sleep(1)
    print('666') if __name__ == '__main__':
    t1 = Thread(target=task,name='线程1') # name 设置线程名
    t2 = Thread(target=task,name='线程2')
    t1.start()
    t2.start()
    time.sleep(2)
    print(t1.isAlive()) # 判断线程是否活着
    print(t1.getName()) # 获取线程名
    t1.setName('子线程-1') # 设置线程的名称
    print(t1.name) # 获取线程名 *** # threading方法
    print(currentThread()) # 获取当前线程的对象
    print(enumerate()) # 返回一个列表,包含所有的线程对象
    print(activeCount()) # 获取当前线程存活个数 ***
    print(f'===主线程{os.getpid()}')

6. 线程join

  • join: 阻塞 告知主线程要等待我子线程执行完毕之后再执行主线程

  • 代码示例:

    from threading import Thread
    import time def task(name):
    print(f'{name} is running')
    time.sleep(1)
    print(f'{name} is gone') if __name__ == '__main__':
    start_time = time.time()
    t1 = Thread(target=task,args=('张三',))
    t2 = Thread(target=task,args=('李四',))
    t3 = Thread(target=task,args=('王五',)) t1.start()
    t1.join()
    t2.start()
    t2.join()
    t3.start()
    t3.join() print(f'===主线程{time.time() - start_time}') # 线程是没有主次之分的.

7. 守护线程

  • 守护线程:等待非守护子线程以及主线程结束之后,结束.

  • 代码示例:

    示例一:简单使用守护线程

    from threading import Thread
    import time def sayhi(name):
    print('你好!')
    time.sleep(2)
    print('%s say hello' %name) if __name__ == '__main__':
    t = Thread(target=sayhi,args=('张三',))
    # 方式1:
    t.setDaemon(True) # 必须在t.start()之前设置
    # 方式2:
    t.daemon = True
    t.start()
    print('主线程')

    示例二:守护线程在非守护线程结束前先结束

    from threading import Thread
    import time def foo():
    print(123) # 第1步
    time.sleep(1)
    print("end123") # 第4步 def bar():
    print(456) # 第2步
    time.sleep(3)
    print("end456") # 第5步 t1=Thread(target=foo)
    t2=Thread(target=bar) t1.daemon=True
    t1.start()
    t2.start()
    print("---main---") # 第3步 # 结果:
    # 123
    # 456
    # ---main---
    # end123
    # end456

    示例三:守护线程在非守护线程结束之后结束

    from threading import Thread
    import time def foo():
    print(123) # 第1步
    time.sleep(3)
    print("end123") def bar():
    print(456) # 第2步
    time.sleep(1)
    print("end456") # 第4步 t1=Thread(target=foo)
    t2=Thread(target=bar) t1.daemon=True
    t1.start()
    t2.start()
    print("main-------") # 第3步 # 结果:
    # 123
    # 456
    # main-------
    # end456

8. 线程互斥锁

  • 多个任务公抢一个数据,保证数据的安全的目的,要让其串行

  • 代码示例

    from threading import Thread
    from threading import Lock
    import time
    import random x = 100
    def task(lock):
    lock.acquire()
    global x
    temp = x
    time.sleep(0.01)
    temp = temp - 1
    x = temp
    lock.release() if __name__ == '__main__':
    mutex = Lock()
    l1 = []
    for i in range(100):
    t = Thread(target=task,args=(mutex,))
    l1.append(t)
    t.start() for i in l1:
    i.join()
    print(f'主线程{x}')

Python并发编程04 /多线程、生产消费者模型、线程进程对比、线程的方法、线程join、守护线程、线程互斥锁的更多相关文章

  1. Python之queue模块以及生产消费者模型

    队列 队列类似于一条管道,元素先进先出,进put(arg),取get() 有一点需要注意的是:队列都是在内存中操作,进程退出,队列清空,另外,队列也是一个阻塞的形态. 队列分类 队列有很多中,但都依赖 ...

  2. Python - Asyncio模块实现的生产消费者模型

    [原创]转载请注明作者Johnthegreat和本文链接 在设计模式中,生产消费者模型占有非常重要的地位,这个模型在现实世界中也有很多有意思的对应场景,比如做包子的人和吃包子的人,当两者速度不匹配时, ...

  3. python并发编程之多线程基础知识点

    1.线程理论知识 概念:指的是一条流水线的工作过程的总称,是一个抽象的概念,是CPU基本执行单位. 进程和线程之间的区别: 1. 进程仅仅是一个资源单位,其中包含程序运行所需的资源,而线程就相当于车间 ...

  4. 29 python 并发编程之多线程理论

    一 什么是线程 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程 车间负责把资源整合 ...

  5. 三 python并发编程之多线程-理论

    一 什么是线程 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程 车间负责把资源整合 ...

  6. python并发编程之多线程理论部分

    阅读目录 一 什么是线程 二 线程的创建开销小 三 线程与进程的区别 四 为何要用多线程 五 多线程的应用举例 六 经典的线程模型(了解) 七 POSIX线程(了解) 八 在用户空间实现的线程(了解) ...

  7. 35、python并发编程之多线程(理论篇)

    一 什么是线程 二 线程的创建开销小 三 线程与进程的区别 四 为何要用多线程 五 多线程的应用举例 六 经典的线程模型(了解) 七 POSIX线程(了解) 八 在用户空间实现的线程(了解) 九 在内 ...

  8. 【Java并发编程】:生产者—消费者模型

    生产者消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一存储空间,生产者向空间里生产数据,而消费者取走数据. 这里实现如下情况的生产--消费模型: 生产者不断交替地生产两组数据“姓 ...

  9. python 并发编程之多线程

    一.线程理论 1.什么是线程 ​ 多线程(即多个控制线程)的概念是,在一个进程中存在多个线程,多个线程共享该进程的地址空间,相当于一个车间内有多条流水线,都共用一个车间的资源. 所以,进程只是用来把资 ...

随机推荐

  1. 今天抠图,Python实现一键换底片!想换什么换什么(附源码)

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 生活中我们会拍很多的证件照,有的要求红底,有的是白底,有的是蓝底,今天不通 ...

  2. (五)使用logback进行日志记录

    原文:https://www.cnblogs.com/taiyonghai/p/9290641.html 引入jar包 此处如果是引用了spring boot则不需要再引一下的jar包了,spring ...

  3. mysql字符串类型(set类型)

    集合 set  不定想项选 类似于 enum枚举,在定义时,也需要指定其已有值! 与字符串相比,优势是: 1, 也是采用 整数进行管理的!采用位运算,从第一位开始为1,逐一x2! 2, 每个集合类型8 ...

  4. CSS基础之简单介绍

    网页诞生初期,没有描述样式的语言,创建了很多用于描述样式的标签.但这些标签破坏了html作为一门结构语言的表现. 于是,W3C在1995年开始起草CSS,提出将结构和样式分离的解决方案. 元素 元素是 ...

  5. STM32单片机应用与全案例实践 /stm32自学笔记 第二版 pdf

    STM32单片机应用与全案例实践pdf https://pan.baidu.com/s/16WrivuLcHvLTwS__Zcwl6Q 4rj3 stm32自学笔记 第二版 pdf https://p ...

  6. StringEscapeUtils防止xss攻击详解

    StringUtils和StringEscapeUtils这两个实用类. 1.转义防止xss攻击 1.转义可以分为下面的几种情况 第一用户输入特殊字符的时候,在提及的时候不做任何处理保持到数据库,当用 ...

  7. python 模块 来了 (调包侠 修炼手册一)

    模块 什么是模块 模块:就是一系列功能的结合体 ,也可以说 一个.py文件包含了 Python 对象定义和Python语 那么 他就 可以说是 一个模块 模块的三种来源: 1.内置的(python解释 ...

  8. 入门大数据---Flink开发环境搭建

    一.安装 Scala 插件 Flink 分别提供了基于 Java 语言和 Scala 语言的 API ,如果想要使用 Scala 语言来开发 Flink 程序,可以通过在 IDEA 中安装 Scala ...

  9. 关于阿里云服务器Linux安装Tomcat后,外网不能访问解决方案

    这里需要提及三个方面的问题   第一个方面:Linux上启动防火墙的问题 当下比较流行的Linux镜像是CentOS,所以防火墙也随之变成了firewall,那么怎么操作这个防火墙呢?   #停止fi ...

  10. 洛谷 P4822 [BJWC2012]冻结

    之前没学分层图,所以先咕了一下hiahiahia. 学完分层图了回来水写题解了. 这道题要用分层图来解.分层图就是在我们决策的时候,再建k层图,一共k+1层,层与层之间是有向边(这个很重要的),权值为 ...