day35——生產者消費者模型、線程

day35

進程:生產者消費者模型

編程思想,模型,設計模式,理論等等,都是交給你一種編程的方法,之後你遇到相似的狀況,套用便可python

生產者消費者模型的三要素
  • 生產者:產生數據的
  • 消費者:接收數據作進一步處理的
  • 容器:盆(隊列)

隊列容器起到什麼做用?編程

  • 起到緩衝的做用,平衡生產力與消費力,解耦
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()

線程的理論知識

什麼是線程

一條流水線的工做流程設計模式

進程:在內存中開啓一個進程空間,而後將主進程的全部資源數據複製一份,而後調用cpu去執行這些代碼多線程

以前的描述不夠具體:併發

開啓一個進程:在內存中開啓一個進程空間,而後將主進程的全部的資源數據複製一份,而後調用線程去執行代碼app

進程是最小的資源單位,線程是最小的執行單位dom

之後你描述開啓一個進程:編輯器

​ 開啓一個進程:進程會在內存中開闢一個進程空間,將主進程的資料數據所有複製一份,線程會執行裏面的代碼ui

線程vs進程
  • 開啓進程的開銷很是大,比開啓線程的開銷大不少
  • 開啓線程的速度很是快,要快幾十倍到上百倍
  • 線程與線程之間能夠共享數據,進程與進程之間需藉助隊列等方法實現通訊
線程的應用

併發:一個cpu看起來像是同時執行多個任務線程

  • 單個進程開啓三個線程,併發的執行任務

  • 開啓三個進程併發的執行任務

    • 文本編輯器:

      一、輸入文字

      二、在屏幕上顯示

      三、保存在磁盤中

      開啓多線程就很是好了:數據共享、開銷小、速度快

線程沒有地位之分,可是一個進程誰在幹活?

只是咱們本身的意思:咱們把執行主程序的線程看成主線程

主線程在執行代碼,當結束以後,你得等待其餘線程結束以後,才能結束本進程

開啓線程的兩種方式

# 第一種方式
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("===主線程")  # 線程是沒有主次之分的

# 第二種方式
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("===主線程")

線程vs進程的代碼對比

開啓速度對比

多線程

from threading import Thread
import time


def task():
    print("hello")


if __name__ == '__main__':
    start_time = time.time()
    # 在主進程下開啓線程
    t1 = Thread(target=task)
    t2 = Thread(target=task)
    t1.start()
    t2.start()
    print("主線程/主進程")
    print(time.time() - start_time)
時間:0.0004723072052001953

多進程

from multiprocessing import Process
import time

def work():
    print("hellow")


if __name__ == '__main__':
    start_time = time.time()
    # 在主進程下開啓線程
    p1 = Process(target=work)
    p2 = Process(target=work)
    p1.start()
    p2.start()
    print("主線程/主進程")
    print(time.time() - start_time)
時間:0.023804903030395508
對比pid

進程

主進程和每一個子進程的pid都不同

from multiprocessing import Process
import os


def 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()}")
結果:
==主12832
子進程:14176
主進程:12832
子進程:11756
主進程:12832

線程

只要是在一個進程內,主線程和每一個線程都同樣

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()}")
結果:
14480
14480
===主線程14480
同一個進程內線程共享內部數據
from threading import Thread
x = 3


def task():
    global x
    x = 100


if __name__ == '__main__':
    t1 = Thread(target=task)
    t1.start()
    t1.join()
    print(f"===主進程{x}")

線程的相關其餘方法(瞭解)

from threading import Thread
from threading import activeCount
from threading import currentThread
from threading import enumerate
import os
import time

# x = 3
def task():
    # print(currentThread())  # 獲取當前線程對象
    # time.sleep(1)
    print(333)

if __name__ == '__main__':
    t1 = Thread(target=task, name="線程1")
    # t2 = Thread(target=task, name="線程2")

    t1.start()
    # t1.setName("朱凡宇")  # 添加name屬性
    # print(t1.getName())   # 查看name屬性
    # print(t1.name)        # 查看name屬性  ****
    # print(t1.isAlive())   # 判斷線程是否活着

    # threading方法
    # print(currentThread())  # 獲取當前線程對象
    # print(enumerate())      # 返回一個列表,包含全部的線程對象
    print(activeCount())      # 返回存活線程的數量   ****
    # t2.start()

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=("海狗1",))
    t2 = Thread(target=task, args=("海狗2",))
    t3 = Thread(target=task, args=("海狗3",))

    t1.start()
    t1.join()
    t2.start()
    t2.join()
    t3.start()
    t3.join()
    print(f"===主線程{time.time() - start_time}")
結果:
海狗1 is running
海狗1 is gone
海狗2 is running
海狗2 is gone
海狗3 is running
海狗3 is gone
===主線程3.0027503967285156

守護進程

# 守護進程
from multiprocessing import Process
import time


def foo():
    print(123)
    time.sleep(1)
    print("end123")


def bar():
    print(456)
    time.sleep(2)
    print("end456")


if __name__ == '__main__':
    p1 = Process(target=foo)
    p2 = Process(target=bar)

    p1.daemon = True
    p1.start()
    p2.start()
    print("===主")
結果:
===主
456
end456

守護線程

守護線程:若是守護線程的生命週期小於其餘線程,則他確定結束,不然等待其餘非守護線程和主線程結束以後結束

# 單線程
from threading import Thread
import time


def sayhi(name):
    # print("你滾!")
    time.sleep(2)
    print(f"{name} say hello")


if __name__ == '__main__':
    t = Thread(target=sayhi, args=("egon",))
    t.daemon = True
    t.start()
    print("主線程")
結果:
主線程

# 多線程一
from threading import Thread
import time


def 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 = True
t1.start()
t2.start()
print("main------------")
結果:
123
456
main------------
end123
end456

# 多線程二
from threading import Thread
import time


def foo():
    print(123)
    time.sleep(3)
    print("end123")


def bar():
    print(456)
    time.sleep(1)
    print("end456")


t1 = Thread(target=foo)
t2 = Thread(target=bar)

t1.daemon = True
t1.start()
t2.start()
print("main------------")
結果:
123
456
main------------
end456

互斥鎖(考點)

問題

from threading import Thread
import time
import random
x = 100


def task():
    # time.sleep(random.randint(1, 2))
    global x
    temp = x
    time.sleep(random.randint(1, 3))
    x = temp -1


if __name__ == '__main__':
    l1 = []
    for i in range(100):
        t = Thread(target=task)
        l1.append(t)
        t.start()

    for i in l1:  # 使主線程沒法先運行print(f"主線程{x}")
        i.join()
    print(f"主線程{x}")
結果: 一直是99

解決:

from threading import Thread
from threading import Lock
import time
import random
x = 100


def task(lock):
    lock.acquire()
    # time.sleep(random.randint(1, 2))
    global x
    temp = x
    # time.sleep(random.randint(1, 3))
    x = temp -1
    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:  # 使主線程沒法先運行print(f"主線程{x}")
        i.join()
    print(f"主線程{x}")
結果:一直是0
相關文章
相關標籤/搜索