Python

Python Standard Library – Thread

Xin chào, hôm nay chúng ta sẽ tìm hiểu về Thread trong python.

Trong lập trình, chúng ta sử dụng Thread để xử lý các tác vụ tốn nhiều thời gian (như load file, capture image frame từ camera) nhằm tránh ảnh hưởng đến tốc độ chung của chương trình.

Có hai cách để thực hiện threading, một là truyền callable object vào Constructor của class Thread, hai là override method run() của superclass Thread.


PASSING A CALLABLE OBJECT TO CONSTRUCTOR

Usage:

Thread(target=functionName, args=(), kwargs={}).start()

Trong đó:

  • target – tên của function cần đưa vào thread;
  • args – một tuple chứa các arguments cần truyền vào function;
  • kwargs – một dict chứa các keyword arguments cần truyền vào function;
  • start() – tạo một thread mới để thực thi function .

Example 1: Image capture from webcam

import cv2
from threading import Thread

class WebcamVideoCapture:
    def __init__(self, src=0):
        # initialize the video camera stream and read the first frame
        # from the stream
        self.stream = cv2.VideoCapture(src)
        (self.grabbed, self.frame) = self.stream.read()

        # initialize the variable used to indicate if the thread should
        # be stopped
        self.stopped = False

    def start(self):
        # start the thread to read frames from the video stream
        Thread(target=self.update).start()
        return self

    def update(self):
        # keep looping infinitely until the thread is stopped
        while True:
            # if the thread indicator variable is set, stop the thread
            if self.stopped:
                self.stream.release()
                return

            # otherwise, read the next frame from the stream
            (self.grabbed, self.frame) = self.stream.read()

    def read(self):
        # return the frame most recently read
        return self.grabbed, self.frame

    def stop(self):
        # indicate that the thread should be stopped
        self.stopped = True

video = WebcamVideoCapture().start()

while True:
    grabbed, image = video.read()
    if not grabbed:
        continue
    cv2.imshow("image", image)
    k = cv2.waitKey(1) & 0xFF
    # nhấn phím q để kết thúc
    if k == ord("q"):
        break

video.stop()
cv2.destroyAllWindows()

Giải thích:
– Dòng 17: chúng ta sử dụng method start() tạo một thread khác để thực thi method update() của class WebcamVideoCapture.
– Dòng 39: khởi tạo đối tượng WebcamVideoCapture.


OVERRIDING THE RUN() METHOD

Đối với phương pháp này chúng ta sẽ kế thừa class Thread và override method run().

Example 2: Overriding the run() method

import cv2
from threading import Thread

class WebcamVideoCapture(Thread):
    def __init__(self, src=0):
        Thread.__init__(self)
        # initialize the video camera stream and read the first frame
        # from the stream
        self.stream = cv2.VideoCapture(src)
        (self.grabbed, self.frame) = self.stream.read()

        # initialize the variable used to indicate if the thread should
        # be stopped
        self.stopped = False

    def run(self):
        self.update()

    def update(self):
        # keep looping infinitely until the thread is stopped
        while True:
            # if the thread indicator variable is set, stop the thread
            if self.stopped:
                self.stream.release()
                return

            # otherwise, read the next frame from the stream
            (self.grabbed, self.frame) = self.stream.read()

    def read(self):
        # return the frame most recently read
        return self.grabbed, self.frame

    def stop(self):
        # indicate that the thread should be stopped
        self.stopped = True

video = WebcamVideoCapture()
video.start()

while True:
    grabbed, image = video.read()
    if not grabbed:
        continue
    cv2.imshow("image", image)
    k = cv2.waitKey(1) & 0xFF
    # nhấn phím q để kết thúc
    if k == ord("q"):
        break

video.stop()
cv2.destroyAllWindows()

Giải thích:
– Dòng 6: kế thừa method __init__() của class Thread;
– Dòng 16,17: override method run() của class Thread;
– Dòng 38,39: khởi tạo đối tượng WebcamVideoCapture và tạo một thread mới để thực thi method update().


SHARING DATA BETWEEN THREADS

Để chia sẻ dữ liệu giữa các thread, chúng ta có thể sử dụng global variables hoặc queue. Trong bài viết này mình sẽ sử dụng global variables cho đơn giản.

Example 3: Sharing variables between threads

from threading import Thread
import time

def printer():
	while number < 9:
		if number % 2 == 1:
			print(number)
			time.sleep(0.1)

def modifier():
	global number
	number = 0
	while number < 9:
		number += 1
		time.sleep(0.2)

Thread(target=modifier, args=()).start()
Thread(target=printer, args=()).start()

Output:
1
1
3
3
5
5
7
7

Giải thích:

Ở function modifier(), biến number được khai báo là global để các function khác có thể tham khảo đến nó. Ở function printer(), vì không cần phải thay đổi giá trị của biến number nên chúng ta có thể tham khảo đến nó mà không cần khai báo global nữa.

Chú ý:  Chúng ta chỉ phải khai báo global cho biến number ở các function khi nào cần thay đổi giá trị của nó. Điều này không cần thiết đối với các thao tác không làm thay đổi giá trị biến number.

Reference:
[1] Python Thread-based parallelism.
[2] Python Global Variable with thread.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s