python 多線程編程

python 多線程編程

使用回調方式

import time
def countdown(n):
    while n > 0:
        print('T-minus', n)
        n -= 1
        time.sleep(5)

# Create and launch a thread
from threading import Thread
t = Thread(target=countdown, args=(10,))
t.start()

把線程放入一個類

from threading import Thread

class CountdownTask:
    def __init__(self):
        self._running = True

    def terminate(self):
        self._running = False

    def run(self, n):
        while self._running and n > 0:
            print('T-minus', n)
            n -= 1
            time.sleep(5)

c = CountdownTask()
t = Thread(target=c.run, args=(10,))
t.start()
c.terminate() # Signal termination
t.join()      # Wait for actual termination (if needed)

注意使用變量 self._running 退出線程的方式html

使用繼承方式

from threading import Threadpython

class CountdownThread(Thread):編程

def __init__(self, n):
    super().__init__()
    self.n = n
def run(self):
    while self.n > 0:

        print('T-minus', self.n)
        self.n -= 1
        time.sleep(5)

c = CountdownThread(5)
c.start()安全

使用 Queue 進行線程間通訊

import Queue
import threading
import time

task_queue = Queue.Queue()


class ThreadTest(threading.Thread):
    def __init__(self, queue):
        threading.Thread.__init__(self)
        self.queue = queue

    def run(self):
        while True:
            msg = self.queue.get()
            print(msg)
            time.sleep(0.1)
            self.queue.task_done()


def main():
    start = time.time()
    # populate queue with data
    for i in range(100):
        task_queue.put("message")

    # spawn a pool of threads, and pass them queue instance
    for i in range(5):
        t = ThreadTest(task_queue)
        t.setDaemon(True)
        t.start()

    # wait on the queue until everything has been processed
    task_queue.join()
    print "Elapsed Time: {}".format(time.time() - start)


if __name__ == "__main__":
    main()

setDaemon 設置爲 True, run 函數中不須要退出,主線程結束後全部子線程退出
若是 setDaemon 設置爲 False,則改成數據結構

def run(self):
    while not self.queue.empty():
        msg = self.queue.get()
        print(msg)
        time.sleep(0.1)
        self.queue.task_done()

而且在主函數結束前 join 全部線程多線程

注意

  • 向隊列中添加數據項時並不會複製此數據項,線程間通訊其實是在線程間傳遞對象引用。若是你擔憂對象的共享狀態,那你最好只傳遞不可修改的數據結構(如:整型、字符串或者元組)或者一個對象的深拷貝。函數

    from queue import Queue
      from threading import Thread
      import copy
    
      # A thread that produces data
      def producer(out_q):
          while True:
              # Produce some data
              ...
              out_q.put(copy.deepcopy(data))
    
      # A thread that consumes data
      def consumer(in_q):
          while True:
              # Get some data
              data = in_q.get()
              # Process the data
              ...
  • q.qsize() , q.full() , q.empty() 等實用方法能夠獲取一個隊列的當前大小和狀態。但要注意,這些方法都不是線程安全的。可能你對一個隊列使用 empty() 判斷出這個隊列爲空,但同時另一個線程可能已經向這個隊列中插入一個數據項。

參考

相關文章
相關標籤/搜索