Python 多執行緒及程式

TuerLueur發表於2018-09-04

threading使用 (工業風案例)

import threading
from time import sleep, ctime


loop = [4, 2]


class ThreadFunc:

    def __init__(self, name):
        self.name = name

    def loop(self, nloop, nsec):
        ```
        :param nloop: loop函式的名稱
        :param nsec: 系統休眠時間
        :return:
        ```
        print(`Start loop `, nloop, `at `, ctime())
        sleep(nsec)
        print(`Done loop `, nloop, ` at `, ctime())


def main():
    print("Starting at: ", ctime())

    # ThreadFunc("loop").loop 跟一下兩個式子相等:
    # t = ThreadFunc("loop")
    # t.loop
    # 以下t1 和  t2的定義方式相等
    t = ThreadFunc("loop")
    t1 = threading.Thread( target = t.loop, args=("LOOP1", 4))
    # 下面這種寫法更西方人,工業化一點
    t2 = threading.Thread( target = ThreadFunc(`loop`).loop, args=("LOOP2", 2))

    # 常見錯誤寫法
    #t1 = threading.Thread(target=ThreadFunc(`loop`).loop(100,4))
    #t2 = threading.Thread(target=ThreadFunc(`loop`).loop(100,2))

    t1.start()
    t2.start()

    t1.join( )
    t2.join()

    print("ALL done at: ", ctime())


if __name__ == `__main__`:
    main()

輸出>>>

Starting at: Sun Sep 2 10:04:47 2018
Start loop LOOP1 at Sun Sep 2 10:04:47 2018
Start loop LOOP2 at Sun Sep 2 10:04:47 2018
Done loop LOOP2 at Sun Sep 2 10:04:49 2018
Done loop LOOP1 at Sun Sep 2 10:04:51 2018
ALL done at: Sun Sep 2 10:04:51 2018

分析:注意:例項化時threading.Thread(target=xxx, args=(xxx,))格式完整,工業風寫法為init了的類的函式,args為其餘param,一行搞定喵

  1. 可以通過設定守護執行緒,使不重要執行緒同主執行緒一同結束

    t1 = threading.Thread(target=fun, args=() )
    # 社會守護執行緒的方法,必須在start之前設定,否則無效
    t1.setDaemon(True)
    #t1.daemon = True
    t1.start()
  2. threading.Lock()的兩個執行緒,競爭資源都acquire(),造成無法release(),最後無法繼續程式。

  3. threading.Semaphore(n)n=允許同時執行執行緒數

  4. threading.Timer(t, func)指定時間開始執行緒

多程式

  1. multiprocessing.Process()直接生成程式

  2. 建立子類生成:

    import multiprocessing
    from time import sleep, ctime
    
    
    class ClockProcess(multiprocessing.Process):
        ```
        兩個函式比較重要
        1. init建構函式
        2. run
        ```
    
        def __init__(self, interval):
            super().__init__()
            self.interval = interval
    
        def run(self):
            while True:
                print("The time is %s" % ctime())
                sleep(self.interval)
    
    
    if __name__ == `__main__`:
        p = ClockProcess(3)
        p.start()
    
        while True:
            print(`sleeping.......`)
            sleep(1)
    

    注意:

    1. __init__裡用super().__init__

    2. 重寫run()

    3. 可以用os.getppid()得到父程式id,用os.getpid()得到本程式id

    4. 建立程式:

      q = multiprocessing.JoinableQueue()
      # 執行消費者程式
      cons_p = multiprocessing.Process (target = consumer, args = (q,))
      cons_p.daemon = True
      cons_p.start()

example:

import multiprocessing
from time import ctime


def consumer(input_q):
    print("Into consumer:", ctime())
    while True:
        item = input_q.get()
        if item is None:
            break
        print("pull", item, "out of q")
    print("Out of consumer:", ctime())


def producer(sequence, output_q):
    for item in sequence:
        print("Into procuder:", ctime())
        output_q.put(item)
        print("Out of procuder:", ctime())


if __name__ == `__main__`:
    q = multiprocessing.Queue()
    cons_p1 = multiprocessing.Process(target=consumer, args=(q,))
    cons_p1.start()

    cons_p2 = multiprocessing.Process (target=consumer, args=(q,))
    cons_p2.start()

    sequence = [1, 2, 3, 4]
    producer(sequence, q)

    q.put(None)
    q.put(None)

    cons_p1.join()
    cons_p2.join()

Into procuder: Tue Sep 4 15:57:37 2018
Out of procuder: Tue Sep 4 15:57:37 2018
Into procuder: Tue Sep 4 15:57:37 2018
Out of procuder: Tue Sep 4 15:57:37 2018
Into procuder: Tue Sep 4 15:57:37 2018
Out of procuder: Tue Sep 4 15:57:37 2018
Into procuder: Tue Sep 4 15:57:37 2018
Out of procuder: Tue Sep 4 15:57:37 2018
Into consumer: Tue Sep 4 15:57:37 2018
pull 1 out of q
pull 2 out of q
pull 3 out of q
pull 4 out of q
Out of consumer: Tue Sep 4 15:57:37 2018
Into consumer: Tue Sep 4 15:57:37 2018
Out of consumer: Tue Sep 4 15:57:37 2018

分析:

  1. multiprocessing.Queue()建立一個程式間佇列
  2. Queue.put()以及Queue.get()為佇列操作,先進先出

相關文章