images
01/10/2020 03:15 am

Lập trình đa luồng với Python

Thread giúp cải thiện tốc độ tính toán của toàn bộ chương trình nhờ tận dụng được lợi thế của CPU ngày nay.

Khởi tạo thread 

Thread giúp cải thiện tốc độ tính toán của toàn bộ chương trình nhờ tận dụng được lợi thế của CPU ngày nay. Để dùng thread trên python3, bạn hãy import thư viện _thread. Đây là thư viện low level cho phép tạo thread với hàm: _thread.start_new_thread(function, (argument1, argument2))

Ví dụ dưới đây tạo 2 thread gọi hàm tính tổng n số nguyên dương đầu tiên:

import _thread

import time

def sum(name, i):

   total = 0

   for k in range(0, i+1):

       total += k

       time.sleep(0.001)

   print('Thread: {}, Total of first {} numbers is: {}'.format(name, i, total))

   return total


if __name__ == "__main__":

   _thread.start_new_thread(sum, ("Thread 1", 100))

   _thread.start_new_thread(sum, ("Thread 2", 100))

   time.sleep(5)


Sử dụng thư viện _thread 

Chúng ta khởi tạo thread mới với hàm tính toán theo cú pháp sau:

_thread.start_new_thread(sum, ("Thread", 100))

Hàm được gọi và các đối số tương ứng được truyền vào thread.

Do tính toán trên các thread nên thứ tự gọi sẽ không quyết định tới thứ tự output.


Lần 1:

  Thread: Thread 1, Total of first 100 numbers is: 5050

  Thread: Thread 2, Total of first 100 numbers is: 5050

Lần 2: 

Thread: Thread 2, Total of first 100 numbers is: 5050

Thread: Thread 1, Total of first 100 numbers is: 5050


Sử dụng thư viện threading 

Có một cách khác là bạn dùng thư viện threading của python với nhiều tính 

năng hỗ trợ dễ dàng hơn cho người lập trình:

import threading

...

   sum1 = threading.Thread(target=sum,args=("Thread 1", 100))

   sum2 = threading.Thread(target=sum,args=("Thread 2", 100))

   sum1.start()

   sum2.start()


Với threading, ta không cần sleep vì các thread được tạo ra với mặc định là các thread non daemon. Với các thread dạng này, chương trình sẽ đợi tới khi thread thực hiện xong mới thoát chương trình.

...

   sum1.start()

   sum2.start()

...


Daemon Thread

Chúng ta thử khai báo thread là daemon xem nhé. Chương trình sẽ chạy mà không ra output gì cả. Vì nó kết thúc trước khi các thread kịp chạy xong.


import threading

...

    sum1 = threading.Thread(target=sum,args=("Thread 1", 100), daemon=True)

   sum2 = threading.Thread(target=sum,args=("Thread 2", 100), daemon=True)

   sum1.start()

   sum2.start()


Vậy có cách nào có thể đợi tới khi chương trình chạy xong? bạn có thể dùng lệnh join() của thread. Lệnh này sẽ treo chương trình và đợi tới khi thread chạy xong.

import threading

...

    sum1 = threading.Thread(target=sum,args=("Thread 1", 100), daemon=True)

   sum2 = threading.Thread(target=sum,args=("Thread 2", 100), daemon=True)

   sum1.start()

   sum2.start()

   sum1.join()

   sum2.join()


Sử dụng ThreadPoolExecutor

Python cũng có thư viện để quản lý thread pool thông qua concurrent.futures.ThreadPoolExecutor. Thread pool sẽ giúp chương trình của bạn quản lý thread sử dụng thread hiệu quả.

Sau khi khai báo thread pool, bạn submit các hàm (task) muốn chạy. Thư viện sẽ trả về cho bạn 1 future giúp bạn kiểm tra trạng thái thông qua hàm Future.done() và lấy kết quả của hàm thông qua future.result()

Lưu ý hàm future.result() sẽ block chương trình cho tới khi future được hoàn thành.

Lúc này chương trình sẽ như sau:

import concurrent.futures

...

if __name__ == "__main__":

   executor = concurrent.futures.ThreadPoolExecutor(5)

   future1 = executor.submit(sum, "task 1 in pool", 1000)

   future2 = executor.submit(sum, "task 2 in pool", 1000)

   print(future1.done())

   time.sleep(2)

   print(future1.done())

   print(future1.result())


Output:

False

Thread: task 2 in pool, Total of first 1000 numbers is: 500500

Thread: task 1 in pool, Total of first 1000 numbers is: 500500

True

500500


Mời các bạn đọc thêm bài Python với hàm Main.


Bạn muốn học Python, cùng tham khảo khóa học này nhé Python cơ bản và ứng dụng thực tế.


- Tech Zone

Thư giãn chút nào!!!

Bài viết liên quan