博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
生产者消费者模型 开启线程的两种方式 多线程与多进程开启速度区别 线程进程pid 统一进程内线程是共享数据的 线程的其他方法 join与守护线程 互斥锁...
阅读量:5173 次
发布时间:2019-06-13

本文共 5923 字,大约阅读时间需要 19 分钟。

生产者消费者模型

进程:

​ 生产者消费者模型

​ 编程思想, 模型, 设计模式, 理论等等, 都是交给你一种编程的方法, 以后遇到类似的情况, 套用即可

生产者消费者模型三要素

​ 生产者: 产生数据的

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

​ 容器: 盆(队列)

队列容器的作用

​ 起到缓冲的作用, 平衡生产力与消费力, 解耦

实例

import timeimport randomfrom multiprocessing import Process, Queuedef 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:            returnif __name__ == '__main__':    q = Queue()    p1 = Process(target=producer, args=(q, "孙宇"))    p2 = Process(target=consumer, args=(q, "海狗"))    p1.start()    p2.start()"""生产者孙宇 生产了1号包子生产者孙宇 生产了2号包子 消费者海狗 吃了1号包子 生产者孙宇 生产了3号包子 消费者海狗 吃了2号包子 生产者孙宇 生产了4号包子生产者孙宇 生产了5号包子 消费者海狗 吃了3号包子  消费者海狗 吃了4号包子  消费者海狗 吃了5号包子 """

开启线程的两种方式

进程是资源单位, 线程是执行单位

什么是线程

​ 一条流水线的工作流程.

进程:

​ 在内存中开启一个进程空间, 然后将主进程的所有的资源数据复制一份, 然后调用CPU去执行这些代码

具体描述进程:

​ 在内存中开启一个进程空间, 然后将主进程的所有的资源数据复制一份, 然后调用线程去执行代码

执行流程

​ 主线程子线程没有地位之分, 但是一个主线程在执行, 执行完, 要等待其他非守护子线程执行完之后, 才能结束主线程, 结束本进程

# 第一种方式from threading import Threadimport timedef 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===主线程李业 is gone"""    # 第二种方式from threading import Threadimport timeclass MyThread(Thread):    def __init__(self, name, l1, s1):        super(MyThread, self).__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("===主线程")"""李业 is running===主线程李业 is gone"""

多线程与多进程开启速度区别

from multiprocessing import Processimport timedef work():    print("hello")if __name__ == '__main__':    start_time = time.time()    lst = []    for i in range(10):        t = Process(target=work)        t.start()        lst.append(t)    for i in lst:        i.join()    print(time.time() - start_time)"""hellohellohellohellohellohellohellohellohellohello1.004307746887207"""# 多线程from threading import Threadimport timedef task():    print("hello")if __name__ == '__main__':    start_time = time.time()    lst = []    for i in range(10):        t = Thread(target=task)        t.start()        lst.append(t)    for i in lst:        i.join()    print(time.time() - start_time)"""hellohellohellohellohellohellohellohellohellohello0.0019998550415039062"""

​ 开启进程的开销非常大, 比开启线程的开销大很多.

​ 开启线程的速度非常快, 要快几十倍到上百倍.

线程进程pid

# 进程pidfrom multiprocessing import Processimport osdef task():    print(f"子进程:{os.getpid()}")    print(f"主进程:{os.getppid()}")if __name__ == '__main__':    p1 = Process(target=task)    p2 = Process(target=task)    p1.start()    p2.start()    print(f"==主:{os.getpid()}")"""==主:51060子进程:51128主进程:51060子进程:42856主进程:51060"""# 线程pidfrom threading import Threadimport osdef task():    print(os.getpid())if __name__ == '__main__':    t = Thread(target=task)    t1 = Thread(target=task)    t.start()    t1.start()    print(f"===主线程:{os.getpid()}")"""5176851768===主线程:51768"""# 多线程在同一个进程内, 所以pid都一样

同一进程内线程是共享数据的

​ 线程与线程之间可以共享数据, 进程与进程之间需要借助队列等方法实现通信

​ 同一进程内的资源数据对于这个进程内的多个线程来说是共享的

1730033-20190823080440213-1259503193.png

线程的应用

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

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

​ 开启三个进程并发的执行任务

​ 文本编辑器:

​ 1.输入文字

​ 2.在屏幕上显示

​ 3.保存在磁盘中

​ 开启多线程就非常简单了:

​ 数据共享, 开销小, 速度快

from threading import Threadx = 3def task():    global x    x = 100if __name__ == '__main__':    t1 = Thread(target=task)    t1.start()    t1.join()    print(f"===主线程{x}")    """===主线程100"""

线程的其他方法

from threading import Thread, current_thread, enumerate, activeCountimport osimport timex = 3def task():    time.sleep(1)    print(666)if __name__ == '__main__':    t1 = Thread(target=task)    t2 = Thread(target=task)    t1.start()    t2.start()    print(t1.isAlive())    # 判断子线程是否存活    print(t1.getName())    # 获取子线程名字    t1.setName("子进程-1")  # 修改子线程名字    print(t1.name)          # 获取子线程的名字 ***    print(current_thread())  # 获取当前线程的内容    print(enumerate())      # 获取当前进程下的所有线程,以列表形式展示    print(activeCount())   # 获取当前进程下的所有存活线程的数量    print(os.getpid())      """TrueThread-1子进程-1<_MainThread(MainThread, started 60668)>[<_MainThread(MainThread, started 60668)>, 
,
]361048666666"""

join 与 守护线程

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

from threading import Threadimport timedef say_hi(name):    print("你滚")    time.sleep(2)    print(f"{name} say hello")if __name__ == '__main__':    t = Thread(target=say_hi, args=("egon",))    # t.setDaemon(True)      # 必须在t.start()前设置, 两种方法都可以    t.daemon = True    t.start()    print("主线程")        # 注意 线程的开启速度比进程要快的多    """你滚主线程"""
from threading import Threadimport timedef foo():    print(123)      time.sleep(1)    print("end123")  def bar():    print(456)      time.sleep(3)    print("end456")  t1=Thread(target=foo)t2=Thread(target=bar)t1.daemon=Truet1.start()t2.start()print("main-------")  """123456main-------end123end456"""

互斥锁

from threading import Threadimport timeimport randomx = 100def task():    global x    temp = x    time.sleep(random.randint(1, 3))    temp = temp - 1    x = tempif __name__ == '__main__':    l1 = []    for i in range(100):        t = Thread(target=task)        l1.append(t)        t.start()    for i in l1:        i.join()    print(f'主线程{x}')"""主线程99"""# 多个任务共抢一个数据, 为了保证数据的安全性, 要让其串行from threading import Threadfrom threading import Lockimport timex = 100def task(lock):    lock.acquire()    global x    temp = x    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()    time.sleep(3)    print(f'主线程{x}')"""主线程0"""

转载于:https://www.cnblogs.com/beichen123/p/11397807.html

你可能感兴趣的文章
set&map
查看>>
集合类总结
查看>>
4.AE中的缩放,书签
查看>>
1.开发准备
查看>>
centos su命令
查看>>
CLR:基元类型、引用类型和值类型
查看>>
dubbo序列化hibernate.LazyInitializationException could not initialize proxy - no Session懒加载异常的解决...
查看>>
jQuery中的事件绑定的几种方式
查看>>
泥塑课
查看>>
setImageBitmap和setImageResource
查看>>
springMVC4 注解配置实例
查看>>
单片机编程
查看>>
Filter in Servlet
查看>>
Linux--SquashFS
查看>>
Application Pool Identities
查看>>
2017-3-24 开通博客园
查看>>
【MySQL性能优化】MySQL常见SQL错误用法
查看>>
Vue2全家桶之一:vue-cli(vue脚手架)超详细教程
查看>>
Struts 2 常用技术
查看>>
树形DP
查看>>