Bạn đã nghe nói về lập trình không đồng bộ trong Python chưa? . Nếu bạn đang tìm hiểu cách sử dụng các tính năng không đồng bộ của Python, thì bạn đã đến đúng nơi
Trong bài viết này, bạn sẽ học
- chương trình đồng bộ là gì
- Chương trình không đồng bộ là gì
- Tại sao bạn có thể muốn viết một chương trình không đồng bộ
- Cách sử dụng các tính năng không đồng bộ của Python
Tất cả các mã ví dụ trong bài viết này đã được thử nghiệm với Python 3. 7. 2. Bạn có thể lấy một bản sao để theo dõi bằng cách nhấp vào liên kết bên dưới
Tải xuống mã. Nhấp vào đây để tải xuống mã mà bạn sẽ sử dụng để tìm hiểu về các tính năng không đồng bộ trong Python trong hướng dẫn này
Hiểu lập trình không đồng bộ
Một chương trình đồng bộ được thực hiện từng bước một. Ngay cả với các lệnh gọi hàm, vòng lặp và phân nhánh có điều kiện, bạn vẫn có thể nghĩ về mã theo cách thực hiện từng bước thực hiện tại một thời điểm. Khi mỗi bước hoàn thành, chương trình sẽ chuyển sang bước tiếp theo
Dưới đây là hai ví dụ về các chương trình hoạt động theo cách này
Các chương trình xử lý hàng loạt thường được tạo dưới dạng các chương trình đồng bộ. Bạn nhận được một số đầu vào, xử lý nó và tạo ra một số đầu ra. Các bước thực hiện lần lượt cho đến khi chương trình đạt được đầu ra mong muốn. Chương trình chỉ cần chú ý đến các bước và thứ tự của chúng
Các chương trình dòng lệnh là các quy trình nhỏ, nhanh chạy trong thiết bị đầu cuối. Các tập lệnh này được sử dụng để tạo một thứ gì đó, chuyển đổi thứ này thành thứ khác, tạo báo cáo hoặc có thể liệt kê một số dữ liệu. Điều này có thể được thể hiện dưới dạng một loạt các bước của chương trình được thực hiện tuần tự cho đến khi hoàn thành chương trình
Một chương trình không đồng bộ hoạt động khác nhau. Nó vẫn mất một bước thực hiện tại một thời điểm. Sự khác biệt là hệ thống có thể không đợi một bước thực hiện hoàn thành trước khi chuyển sang bước tiếp theo
Điều này có nghĩa là chương trình sẽ chuyển sang các bước thực hiện trong tương lai mặc dù bước trước đó chưa kết thúc và vẫn đang chạy ở nơi khác. Điều này cũng có nghĩa là chương trình biết phải làm gì khi bước trước chạy xong
Tại sao bạn muốn viết một chương trình theo cách này?
Loại bỏ các quảng cáoXây dựng một máy chủ web đồng bộ
Đơn vị công việc cơ bản của máy chủ web ít nhiều cũng giống như xử lý hàng loạt. Máy chủ sẽ nhận một số đầu vào, xử lý nó và tạo đầu ra. Được viết dưới dạng chương trình đồng bộ, điều này sẽ tạo ra một máy chủ web đang hoạt động
Nó cũng sẽ là một máy chủ web hoàn toàn khủng khiếp
Tại sao? . Mục đích thực sự là xử lý hàng trăm, thậm chí hàng nghìn đơn vị công việc nhanh nhất có thể. Điều này có thể xảy ra trong thời gian dài và thậm chí một số đơn vị công việc có thể đến cùng một lúc
Một máy chủ web đồng bộ có thể được thực hiện tốt hơn? . Thật không may, có những hạn chế đối với phương pháp này. Kết quả có thể là một máy chủ web không phản hồi đủ nhanh, không thể xử lý đủ công việc hoặc thậm chí là một máy chủ hết thời gian chờ khi công việc chồng chất lên nhau
Ghi chú. Có những hạn chế khác mà bạn có thể thấy nếu cố gắng tối ưu hóa phương pháp trên. Chúng bao gồm tốc độ mạng, tốc độ tệp IO, tốc độ truy vấn cơ sở dữ liệu và tốc độ của các dịch vụ được kết nối khác, v.v. Tất cả những thứ này đều có điểm chung là chúng đều là các hàm IO. Tất cả các mục này đều chậm hơn so với tốc độ xử lý của CPU
Trong một chương trình đồng bộ, nếu một bước thực hiện bắt đầu một truy vấn cơ sở dữ liệu, thì về cơ bản, CPU sẽ không hoạt động cho đến khi truy vấn cơ sở dữ liệu được trả về. Đối với các chương trình định hướng hàng loạt, đây không phải là ưu tiên trong hầu hết thời gian. Xử lý kết quả của hoạt động IO đó là mục tiêu. Thông thường, quá trình này có thể mất nhiều thời gian hơn chính thao tác IO. Mọi nỗ lực tối ưu hóa sẽ được tập trung vào công việc xử lý, không phải IO
Các kỹ thuật lập trình không đồng bộ cho phép các chương trình của bạn tận dụng các quy trình IO tương đối chậm bằng cách giải phóng CPU để thực hiện công việc khác
Nghĩ khác về lập trình
Khi bạn bắt đầu cố gắng hiểu lập trình không đồng bộ, bạn có thể thấy rất nhiều cuộc thảo luận về tầm quan trọng của việc chặn hoặc viết mã không chặn. [Cá nhân tôi gặp khó khăn trong việc nắm bắt tốt các khái niệm này từ những người tôi đã hỏi và tài liệu tôi đọc. ]
Mã không chặn là gì?
Viết chương trình không đồng bộ đòi hỏi bạn phải nghĩ khác về lập trình. Mặc dù cách suy nghĩ mới này có thể khiến bạn khó hiểu, nhưng đây cũng là một bài tập thú vị. Đó là bởi vì thế giới thực gần như hoàn toàn không đồng bộ và cách bạn tương tác với nó cũng vậy.
Hãy tưởng tượng điều này. bạn là cha mẹ đang cố gắng làm nhiều việc cùng một lúc. Bạn phải cân bằng sổ séc, giặt giũ và để mắt đến bọn trẻ. Bằng cách nào đó, bạn có thể làm tất cả những việc này cùng một lúc mà không cần suy nghĩ về nó. Hãy phá vỡ nó
Cân đối sổ séc là nhiệm vụ đồng bộ. Bước này nối tiếp bước kia cho đến khi hoàn thành. Bạn đang tự mình làm tất cả công việc
Tuy nhiên, bạn có thể thoát khỏi sổ séc để giặt đồ. Bạn lấy quần áo ra khỏi máy sấy, di chuyển quần áo từ máy giặt sang máy sấy và bắt đầu một mẻ giặt khác trong máy giặt
Làm việc với máy giặt và máy sấy là một nhiệm vụ đồng bộ, nhưng phần lớn công việc diễn ra sau khi máy giặt và máy sấy được khởi động. Khi bạn đã hoàn thành chúng, bạn có thể bỏ đi và quay lại nhiệm vụ sổ séc. Tại thời điểm này, các nhiệm vụ của máy giặt và máy sấy đã trở nên không đồng bộ. Máy giặt và máy sấy sẽ chạy độc lập cho đến khi còi kêu [thông báo cho bạn biết rằng công việc cần chú ý]
Theo dõi con bạn là một nhiệm vụ không đồng bộ khác. Khi chúng được thiết lập và chơi, phần lớn chúng có thể làm như vậy một cách độc lập. Điều này thay đổi khi ai đó cần được chú ý, chẳng hạn như khi ai đó bị đói hoặc bị thương. Khi một trong những đứa trẻ của bạn hét lên báo động, bạn phản ứng. Những đứa trẻ là một nhiệm vụ lâu dài với mức độ ưu tiên cao. Xem chúng thay thế bất kỳ nhiệm vụ nào khác mà bạn có thể đang làm, chẳng hạn như sổ séc hoặc giặt ủi
Những ví dụ này có thể giúp minh họa các khái niệm về mã chặn và mã không chặn. Hãy nghĩ về điều này trong thuật ngữ lập trình. Trong ví dụ này, bạn giống như CPU. Trong khi bạn đang di chuyển đồ giặt xung quanh, bạn [CPU] đang bận và bị chặn làm công việc khác, chẳng hạn như cân bằng sổ séc. Nhưng không sao vì nhiệm vụ tương đối nhanh
Mặt khác, việc khởi động máy giặt và máy sấy không cản trở bạn thực hiện các tác vụ khác. Đây là một chức năng không đồng bộ vì bạn không phải đợi nó hoàn thành. Sau khi nó bắt đầu, bạn có thể quay lại thứ khác. Đây được gọi là chuyển đổi ngữ cảnh. bối cảnh công việc bạn đang làm đã thay đổi và chuông của máy sẽ thông báo cho bạn trong tương lai khi nhiệm vụ giặt là hoàn tất
Là một con người, đây là cách bạn làm việc mọi lúc. Bạn làm nhiều việc cùng một lúc một cách tự nhiên mà không cần suy nghĩ về nó. Là một nhà phát triển, mẹo là làm thế nào để chuyển loại hành vi này thành mã thực hiện cùng loại
cha mẹ lập trình. Không dễ như bề ngoài
Nếu bạn nhận ra chính mình [hoặc cha mẹ của bạn] trong ví dụ trên thì thật tuyệt. Bạn đã hiểu rõ hơn về lập trình không đồng bộ. Một lần nữa, bạn có thể chuyển ngữ cảnh giữa các tác vụ cạnh tranh khá dễ dàng, chọn một số tác vụ và tiếp tục các tác vụ khác. Bây giờ bạn sẽ thử và lập trình hành vi này thành cha mẹ ảo
Thử nghiệm suy nghĩ #1. Cha mẹ đồng bộ
Bạn sẽ tạo một chương trình mẹ như thế nào để thực hiện các tác vụ trên một cách hoàn toàn đồng bộ? . Cha mẹ trông chừng con cái trong khi chờ đợi điều gì đó xảy ra có thể cần sự chú ý của chúng. Tuy nhiên, không có gì khác [như sổ séc hoặc đồ giặt] sẽ được thực hiện trong tình huống này
Giờ đây, bạn có thể sắp xếp lại mức độ ưu tiên cho các nhiệm vụ theo bất kỳ cách nào bạn muốn, nhưng chỉ một trong số chúng sẽ xảy ra vào bất kỳ thời điểm nào. Đây là kết quả của cách làm đồng bộ, từng bước. Giống như máy chủ web đồng bộ được mô tả ở trên, điều này sẽ hoạt động, nhưng nó có thể không phải là cách tốt nhất để tồn tại. Cha mẹ sẽ không thể hoàn thành bất kỳ nhiệm vụ nào khác cho đến khi bọn trẻ ngủ thiếp đi. Tất cả các nhiệm vụ khác sẽ xảy ra sau đó, vào ban đêm. [Một vài tuần như vậy và nhiều bậc cha mẹ thực sự có thể nhảy ra khỏi cửa sổ. ]
Loại bỏ các quảng cáoThử nghiệm suy nghĩ #2. Cha mẹ thăm dò ý kiến
Nếu bạn đã sử dụng tính năng bỏ phiếu, thì bạn có thể thay đổi mọi thứ để hoàn thành nhiều tác vụ. Theo cách tiếp cận này, cha mẹ sẽ định kỳ thoát khỏi nhiệm vụ hiện tại và kiểm tra xem có nhiệm vụ nào khác cần chú ý không.
Hãy tạo khoảng thời gian bỏ phiếu giống như mười lăm phút. Bây giờ, cứ sau mười lăm phút, cha mẹ của bạn sẽ kiểm tra xem máy giặt, máy sấy hoặc trẻ em có cần chú ý gì không. Nếu không, phụ huynh có thể quay lại làm việc trên sổ séc. Tuy nhiên, nếu bất kỳ nhiệm vụ nào trong số đó cần chú ý, thì phụ huynh sẽ quan tâm đến việc đó trước khi quay lại sổ séc. Chu kỳ này tiếp tục cho đến khi hết thời gian chờ tiếp theo của vòng bỏ phiếu
Cách tiếp cận này cũng hiệu quả vì nhiều nhiệm vụ đang được chú ý. Tuy nhiên, có một vài vấn đề
Phụ huynh có thể dành nhiều thời gian để kiểm tra những thứ không cần chú ý. Máy giặt và máy sấy chưa xong, và bọn trẻ không cần quan tâm trừ khi có điều gì đó bất ngờ xảy ra
Phụ huynh có thể bỏ lỡ các nhiệm vụ đã hoàn thành cần chú ý. Chẳng hạn, nếu máy giặt hoàn thành chu kỳ của nó khi bắt đầu khoảng thời gian bỏ phiếu, thì nó sẽ không nhận được bất kỳ sự chú ý nào trong tối đa mười lăm phút. Hơn nữa, trông chừng bọn trẻ được cho là nhiệm vụ ưu tiên cao nhất. Họ không thể chịu đựng được mười lăm phút mà không chú ý khi có điều gì đó có thể sai nghiêm trọng.
Bạn có thể giải quyết những vấn đề này bằng cách rút ngắn khoảng thời gian bỏ phiếu, nhưng bây giờ cha mẹ của bạn [CPU] sẽ dành nhiều thời gian hơn để chuyển ngữ cảnh giữa các tác vụ. Đây là khi bạn bắt đầu đạt đến điểm lợi nhuận giảm dần. [Một lần nữa, một vài tuần sống như thế này và, chà… Xem bình luận trước về cửa sổ và nhảy. ]
Thử nghiệm suy nghĩ #3. Cha mẹ luồng
“Giá như tôi có thể nhân bản chính mình…” Nếu là cha mẹ, chắc hẳn bạn cũng từng có suy nghĩ tương tự. Vì bạn đang lập trình cha mẹ ảo, nên về cơ bản, bạn có thể thực hiện việc này bằng cách sử dụng phân luồng. Đây là cơ chế cho phép nhiều phần của một chương trình chạy cùng lúc. Mỗi phần mã chạy độc lập được gọi là một luồng và tất cả các luồng chia sẻ cùng một không gian bộ nhớ
Nếu bạn coi mỗi tác vụ là một phần của một chương trình, thì bạn có thể tách chúng ra và chạy chúng dưới dạng các luồng. Nói cách khác, bạn có thể “sao chép” cha mẹ, tạo một phiên bản cho mỗi tác vụ. theo dõi lũ trẻ, giám sát máy giặt, giám sát máy sấy và cân bằng sổ séc. Tất cả những “bản sao” này đang chạy độc lập
Điều này nghe có vẻ là một giải pháp khá hay, nhưng cũng có một số vấn đề ở đây. Một là bạn sẽ phải thông báo rõ ràng cho từng cá thể mẹ phải làm gì trong chương trình của mình. Điều này có thể dẫn đến một số vấn đề vì tất cả các phiên bản đều chia sẻ mọi thứ trong không gian chương trình
Ví dụ: giả sử Phụ huynh A đang giám sát máy sấy. Phụ huynh A thấy quần áo đã khô nên điều khiển máy sấy và bắt đầu lấy quần áo ra. Cùng lúc đó, Phụ huynh B thấy máy giặt đã xong nên điều khiển máy giặt và bắt đầu lấy quần áo ra. Tuy nhiên, Phụ huynh B cũng cần kiểm soát máy sấy để cho quần áo ướt vào bên trong. Điều này không thể xảy ra vì Phụ huynh A hiện đang có quyền kiểm soát máy sấy
Một lúc sau, phụ huynh A đã dỡ xong quần áo. Bây giờ họ muốn kiểm soát máy giặt và bắt đầu chuyển quần áo vào máy sấy trống. Điều này cũng không thể xảy ra vì Phụ huynh B hiện có quyền kiểm soát máy giặt
Hai bố mẹ này giờ đã. Cả hai đều có quyền kiểm soát tài nguyên của mình và muốn kiểm soát tài nguyên khác. Họ sẽ đợi mãi cho đến khi phiên bản gốc khác giải phóng quyền kiểm soát. Là lập trình viên, bạn phải viết mã để giải quyết tình huống này
Ghi chú. Các chương trình theo luồng cho phép bạn tạo nhiều đường dẫn thực thi song song, tất cả đều chia sẻ cùng một không gian bộ nhớ. Đây vừa là ưu điểm vừa là nhược điểm. Mọi bộ nhớ được chia sẻ giữa các luồng đều phải tuân theo một hoặc nhiều luồng đang cố gắng sử dụng cùng một bộ nhớ được chia sẻ cùng một lúc. Điều này có thể dẫn đến hỏng dữ liệu, đọc dữ liệu ở trạng thái không hợp lệ và dữ liệu nói chung là lộn xộn
Trong lập trình luồng, chuyển đổi ngữ cảnh xảy ra dưới sự kiểm soát của hệ thống, không phải lập trình viên. Hệ thống kiểm soát thời điểm chuyển ngữ cảnh và thời điểm cấp quyền truy cập cho các luồng vào dữ liệu được chia sẻ, do đó thay đổi ngữ cảnh về cách bộ nhớ đang được sử dụng. Tất cả các loại sự cố này đều có thể quản lý được trong mã luồng, nhưng rất khó để hiểu đúng và khó gỡ lỗi khi sai
Đây là một vấn đề khác có thể phát sinh từ luồng. Giả sử một đứa trẻ bị thương và cần được đưa đi cấp cứu. Phụ huynh C được giao nhiệm vụ trông con nên đưa con đi ngay. Tại phòng chăm sóc khẩn cấp, Phụ huynh C cần viết một tấm séc khá lớn để trang trải chi phí gặp bác sĩ
Trong khi đó, phụ huynh D ở nhà làm sổ sách chi phiếu. Họ không biết tấm séc lớn này được viết, vì vậy họ rất ngạc nhiên khi tài khoản séc của gia đình đột nhiên bị thấu chi.
Hãy nhớ rằng, hai phiên bản gốc này đang hoạt động trong cùng một chương trình. Tài khoản séc của gia đình là tài nguyên được chia sẻ, vì vậy bạn phải tìm ra cách để phụ huynh trông trẻ thông báo cho phụ huynh đang cân đối sổ séc. Mặt khác, bạn cần cung cấp một số loại cơ chế khóa để tài nguyên sổ séc chỉ có thể được sử dụng bởi một phụ huynh tại một thời điểm, với các bản cập nhật
Sử dụng các tính năng không đồng bộ của Python trong thực tế
Bây giờ, bạn sẽ thực hiện một số cách tiếp cận được nêu trong các thử nghiệm tưởng tượng ở trên và biến chúng thành các chương trình Python hoạt động được
Tất cả các ví dụ trong bài viết này đã được thử nghiệm với Python 3. 7. 2. Tệp
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
2 cho biết bạn sẽ cần cài đặt mô-đun nào để chạy tất cả các ví dụ. Nếu bạn chưa tải xuống tệp, bạn có thể thực hiện ngay bây giờTải xuống mã. Nhấp vào đây để tải xuống mã mà bạn sẽ sử dụng để tìm hiểu về các tính năng không đồng bộ trong Python trong hướng dẫn này
Bạn cũng có thể muốn thiết lập môi trường ảo Python để chạy mã để bạn không can thiệp vào Python hệ thống của mình
Loại bỏ các quảng cáoLập trình đồng bộ
Ví dụ đầu tiên này cho thấy một cách có phần giả tạo để có một tác vụ truy xuất công việc từ một hàng đợi và xử lý công việc đó. Một hàng đợi trong Python là một cấu trúc dữ liệu FIFO [vào trước ra trước] đẹp. Nó cung cấp các phương thức để đặt mọi thứ vào hàng đợi và lấy chúng ra một lần nữa theo thứ tự chúng được đưa vào
Trong trường hợp này, công việc là lấy một số từ hàng đợi và có một vòng lặp đếm đến số đó. Nó in ra bàn điều khiển khi vòng lặp bắt đầu và một lần nữa để xuất tổng số. Chương trình này trình bày một cách để nhiều tác vụ đồng bộ xử lý công việc trong hàng đợi
Chương trình có tên
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
3 trong kho lưu trữ được liệt kê đầy đủ bên dưới 1import queue
2
3def task[name, work_queue]:
4 if work_queue.empty[]:
5 print[f"Task {name} nothing to do"]
6 else:
7 while not work_queue.empty[]:
8 count = work_queue.get[]
9 total = 0
10 print[f"Task {name} running"]
11 for x in range[count]:
12 total += 1
13 print[f"Task {name} total: {total}"]
14
15def main[]:
16 """
17 This is the main entry point for the program
18 """
19 # Create the queue of work
20 work_queue = queue.Queue[]
21
22 # Put some work in the queue
23 for work in [15, 10, 5, 2]:
24 work_queue.put[work]
25
26 # Create some synchronous tasks
27 tasks = [[task, "One", work_queue], [task, "Two", work_queue]]
28
29 # Run the tasks
30 for t, n, q in tasks:
31 t[n, q]
32
33if __name__ == "__main__":
34 main[]
Hãy xem mỗi dòng làm gì
- Dòng 1 nhập mô-đun
4. Đây là nơi chương trình lưu trữ công việc cần thực hiện bởi các tác vụTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 3 đến 13 định nghĩa
5. Hàm này lấy công việc ra khỏiTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
6 và xử lý công việc cho đến khi không còn việc gì để làmTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 15 định nghĩa
7 để chạy các tác vụ của chương trìnhTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 20 tạo
6. Tất cả các tác vụ sử dụng tài nguyên được chia sẻ này để truy xuất công việcTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 23 đến 24 đưa công việc vào
6. Trong trường hợp này, đó chỉ là một số giá trị ngẫu nhiên cho các tác vụ xử lýTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 27 tạo danh sách các bộ nhiệm vụ, với các giá trị tham số, các nhiệm vụ đó sẽ được chuyển
- Các dòng 30 đến 31 lặp qua danh sách các bộ nhiệm vụ, gọi từng bộ và chuyển các giá trị tham số đã xác định trước đó
- Dòng 34 gọi
7 để chạy chương trìnhTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
Nhiệm vụ trong chương trình này chỉ là một hàm chấp nhận một chuỗi và một hàng đợi làm tham số. Khi được thực thi, nó sẽ tìm mọi thứ trong hàng đợi để xử lý. Nếu có việc phải làm, thì nó sẽ lấy các giá trị ra khỏi hàng đợi, bắt đầu vòng lặp
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
01 để đếm đến giá trị đó và xuất ra tổng số ở cuối. Nó tiếp tục hoàn thành công việc khỏi hàng đợi cho đến khi không còn gì và nó thoátKhi chương trình này được chạy, nó sẽ tạo ra kết quả như bạn thấy bên dưới
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
Điều này cho thấy rằng
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
02 làm tất cả công việc. Vòng lặp Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
03 mà Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
02 truy cập trong vòng Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
5 tiêu thụ tất cả công việc trên hàng đợi và xử lý nó. Khi vòng lặp đó thoát ra, Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
06 sẽ có cơ hội chạy. Tuy nhiên, nó thấy rằng hàng đợi trống, vì vậy Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
06 in ra một câu lệnh nói rằng nó không có gì để làm và sau đó thoát ra. Không có gì trong mã cho phép cả Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
02 và Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
06 chuyển ngữ cảnh và làm việc cùng nhauĐồng thời hợp tác đơn giản
Phiên bản tiếp theo của chương trình cho phép hai tác vụ hoạt động cùng nhau. Thêm câu lệnh
1import queue
2
3def task[name, work_queue]:
4 if work_queue.empty[]:
5 print[f"Task {name} nothing to do"]
6 else:
7 while not work_queue.empty[]:
8 count = work_queue.get[]
9 total = 0
10 print[f"Task {name} running"]
11 for x in range[count]:
12 total += 1
13 print[f"Task {name} total: {total}"]
14
15def main[]:
16 """
17 This is the main entry point for the program
18 """
19 # Create the queue of work
20 work_queue = queue.Queue[]
21
22 # Put some work in the queue
23 for work in [15, 10, 5, 2]:
24 work_queue.put[work]
25
26 # Create some synchronous tasks
27 tasks = [[task, "One", work_queue], [task, "Two", work_queue]]
28
29 # Run the tasks
30 for t, n, q in tasks:
31 t[n, q]
32
33if __name__ == "__main__":
34 main[]
00 có nghĩa là vòng lặp sẽ mang lại quyền kiểm soát tại điểm đã chỉ định trong khi vẫn duy trì ngữ cảnh của nó. Bằng cách này, tác vụ tạo năng suất có thể được khởi động lại sauCâu lệnh
1import queue
2
3def task[name, work_queue]:
4 if work_queue.empty[]:
5 print[f"Task {name} nothing to do"]
6 else:
7 while not work_queue.empty[]:
8 count = work_queue.get[]
9 total = 0
10 print[f"Task {name} running"]
11 for x in range[count]:
12 total += 1
13 print[f"Task {name} total: {total}"]
14
15def main[]:
16 """
17 This is the main entry point for the program
18 """
19 # Create the queue of work
20 work_queue = queue.Queue[]
21
22 # Put some work in the queue
23 for work in [15, 10, 5, 2]:
24 work_queue.put[work]
25
26 # Create some synchronous tasks
27 tasks = [[task, "One", work_queue], [task, "Two", work_queue]]
28
29 # Run the tasks
30 for t, n, q in tasks:
31 t[n, q]
32
33if __name__ == "__main__":
34 main[]
00 biến Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
5 thành một trình tạo. Hàm tạo được gọi giống như bất kỳ hàm nào khác trong Python, nhưng khi câu lệnh 1import queue
2
3def task[name, work_queue]:
4 if work_queue.empty[]:
5 print[f"Task {name} nothing to do"]
6 else:
7 while not work_queue.empty[]:
8 count = work_queue.get[]
9 total = 0
10 print[f"Task {name} running"]
11 for x in range[count]:
12 total += 1
13 print[f"Task {name} total: {total}"]
14
15def main[]:
16 """
17 This is the main entry point for the program
18 """
19 # Create the queue of work
20 work_queue = queue.Queue[]
21
22 # Put some work in the queue
23 for work in [15, 10, 5, 2]:
24 work_queue.put[work]
25
26 # Create some synchronous tasks
27 tasks = [[task, "One", work_queue], [task, "Two", work_queue]]
28
29 # Run the tasks
30 for t, n, q in tasks:
31 t[n, q]
32
33if __name__ == "__main__":
34 main[]
00 được thực thi, quyền điều khiển được trả về cho người gọi hàm. Đây thực chất là một công tắc ngữ cảnh, khi điều khiển chuyển từ chức năng trình tạo sang trình gọiPhần thú vị là quyền điều khiển có thể được trả lại cho hàm tạo bằng cách gọi
1import queue
2
3def task[name, work_queue]:
4 if work_queue.empty[]:
5 print[f"Task {name} nothing to do"]
6 else:
7 while not work_queue.empty[]:
8 count = work_queue.get[]
9 total = 0
10 print[f"Task {name} running"]
11 for x in range[count]:
12 total += 1
13 print[f"Task {name} total: {total}"]
14
15def main[]:
16 """
17 This is the main entry point for the program
18 """
19 # Create the queue of work
20 work_queue = queue.Queue[]
21
22 # Put some work in the queue
23 for work in [15, 10, 5, 2]:
24 work_queue.put[work]
25
26 # Create some synchronous tasks
27 tasks = [[task, "One", work_queue], [task, "Two", work_queue]]
28
29 # Run the tasks
30 for t, n, q in tasks:
31 t[n, q]
32
33if __name__ == "__main__":
34 main[]
04 trên trình tạo. Đây là một chuyển đổi ngữ cảnh trở lại hàm tạo, giúp chọn thực thi với tất cả các biến hàm đã được xác định trước khi 1import queue
2
3def task[name, work_queue]:
4 if work_queue.empty[]:
5 print[f"Task {name} nothing to do"]
6 else:
7 while not work_queue.empty[]:
8 count = work_queue.get[]
9 total = 0
10 print[f"Task {name} running"]
11 for x in range[count]:
12 total += 1
13 print[f"Task {name} total: {total}"]
14
15def main[]:
16 """
17 This is the main entry point for the program
18 """
19 # Create the queue of work
20 work_queue = queue.Queue[]
21
22 # Put some work in the queue
23 for work in [15, 10, 5, 2]:
24 work_queue.put[work]
25
26 # Create some synchronous tasks
27 tasks = [[task, "One", work_queue], [task, "Two", work_queue]]
28
29 # Run the tasks
30 for t, n, q in tasks:
31 t[n, q]
32
33if __name__ == "__main__":
34 main[]
00 vẫn còn nguyên vẹnVòng lặp
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
03 trong Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
7 tận dụng lợi thế này khi nó gọi 1import queue
2
3def task[name, work_queue]:
4 if work_queue.empty[]:
5 print[f"Task {name} nothing to do"]
6 else:
7 while not work_queue.empty[]:
8 count = work_queue.get[]
9 total = 0
10 print[f"Task {name} running"]
11 for x in range[count]:
12 total += 1
13 print[f"Task {name} total: {total}"]
14
15def main[]:
16 """
17 This is the main entry point for the program
18 """
19 # Create the queue of work
20 work_queue = queue.Queue[]
21
22 # Put some work in the queue
23 for work in [15, 10, 5, 2]:
24 work_queue.put[work]
25
26 # Create some synchronous tasks
27 tasks = [[task, "One", work_queue], [task, "Two", work_queue]]
28
29 # Run the tasks
30 for t, n, q in tasks:
31 t[n, q]
32
33if __name__ == "__main__":
34 main[]
08. Câu lệnh này khởi động lại tác vụ tại điểm mà nó đã tạo ra trước đó. Tất cả điều này có nghĩa là bạn đang kiểm soát khi chuyển ngữ cảnh xảy ra. khi câu lệnh 1import queue
2
3def task[name, work_queue]:
4 if work_queue.empty[]:
5 print[f"Task {name} nothing to do"]
6 else:
7 while not work_queue.empty[]:
8 count = work_queue.get[]
9 total = 0
10 print[f"Task {name} running"]
11 for x in range[count]:
12 total += 1
13 print[f"Task {name} total: {total}"]
14
15def main[]:
16 """
17 This is the main entry point for the program
18 """
19 # Create the queue of work
20 work_queue = queue.Queue[]
21
22 # Put some work in the queue
23 for work in [15, 10, 5, 2]:
24 work_queue.put[work]
25
26 # Create some synchronous tasks
27 tasks = [[task, "One", work_queue], [task, "Two", work_queue]]
28
29 # Run the tasks
30 for t, n, q in tasks:
31 t[n, q]
32
33if __name__ == "__main__":
34 main[]
00 được thực thi trong Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
5Đây là một hình thức hợp tác đa nhiệm. Chương trình đang mang lại quyền kiểm soát bối cảnh hiện tại của nó để thứ khác có thể chạy. Trong trường hợp này, nó cho phép vòng lặp
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
03 trong Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
7 chạy hai phiên bản của Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
5 dưới dạng hàm tạo. Mỗi phiên bản sử dụng công việc từ cùng một hàng đợi. Đây là một loại thông minh, nhưng cũng cần rất nhiều công việc để có được kết quả như chương trình đầu tiên. Chương trình Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
44 minh họa đồng thời đơn giản này và được liệt kê bên dướiTask One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
0Đây là những gì đang xảy ra trong đoạn mã trên
- Các dòng 3 đến 11 định nghĩa
5 như trước, nhưng việc thêmTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
00 vào Dòng 10 biến hàm thành một trình tạo. Đây là nơi thực hiện chuyển đổi ngữ cảnh và điều khiển được trao lại cho vòng lặp1import queue 2 3def task[name, work_queue]: 4 if work_queue.empty[]: 5 print[f"Task {name} nothing to do"] 6 else: 7 while not work_queue.empty[]: 8 count = work_queue.get[] 9 total = 0 10 print[f"Task {name} running"] 11 for x in range[count]: 12 total += 1 13 print[f"Task {name} total: {total}"] 14 15def main[]: 16 """ 17 This is the main entry point for the program 18 """ 19 # Create the queue of work 20 work_queue = queue.Queue[] 21 22 # Put some work in the queue 23 for work in [15, 10, 5, 2]: 24 work_queue.put[work] 25 26 # Create some synchronous tasks 27 tasks = [[task, "One", work_queue], [task, "Two", work_queue]] 28 29 # Run the tasks 30 for t, n, q in tasks: 31 t[n, q] 32 33if __name__ == "__main__": 34 main[]
03 trongTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
7Task One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 25 tạo danh sách nhiệm vụ, nhưng theo cách hơi khác so với cách bạn thấy trong mã ví dụ trước. Trong trường hợp này, mỗi tác vụ được gọi với các tham số của nó như được nhập vào biến danh sách
49. Điều này là cần thiết để chức năng tạoTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
5 chạy lần đầu tiênTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Các dòng 31 đến 36 là các sửa đổi đối với vòng lặp
03 trongTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
7 cho phépTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
5 chạy hợp tác. Đây là nơi điều khiển quay trở lại từng phiên bản củaTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
5 khi nó mang lại kết quả, cho phép vòng lặp tiếp tục và chạy một tác vụ khácTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 32 trả lại quyền điều khiển cho
5 và tiếp tục thực hiện sau thời điểm màTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
00 được gọi1import queue 2 3def task[name, work_queue]: 4 if work_queue.empty[]: 5 print[f"Task {name} nothing to do"] 6 else: 7 while not work_queue.empty[]: 8 count = work_queue.get[] 9 total = 0 10 print[f"Task {name} running"] 11 for x in range[count]: 12 total += 1 13 print[f"Task {name} total: {total}"] 14 15def main[]: 16 """ 17 This is the main entry point for the program 18 """ 19 # Create the queue of work 20 work_queue = queue.Queue[] 21 22 # Put some work in the queue 23 for work in [15, 10, 5, 2]: 24 work_queue.put[work] 25 26 # Create some synchronous tasks 27 tasks = [[task, "One", work_queue], [task, "Two", work_queue]] 28 29 # Run the tasks 30 for t, n, q in tasks: 31 t[n, q] 32 33if __name__ == "__main__": 34 main[]
- Dòng 36 đặt biến
87. Vòng lặpTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
03 kết thúc khi tất cả các tác vụ đã được hoàn thành và xóa khỏiTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
49Task One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
Đây là đầu ra được tạo ra khi bạn chạy chương trình này
1import queue
2
3def task[name, work_queue]:
4 if work_queue.empty[]:
5 print[f"Task {name} nothing to do"]
6 else:
7 while not work_queue.empty[]:
8 count = work_queue.get[]
9 total = 0
10 print[f"Task {name} running"]
11 for x in range[count]:
12 total += 1
13 print[f"Task {name} total: {total}"]
14
15def main[]:
16 """
17 This is the main entry point for the program
18 """
19 # Create the queue of work
20 work_queue = queue.Queue[]
21
22 # Put some work in the queue
23 for work in [15, 10, 5, 2]:
24 work_queue.put[work]
25
26 # Create some synchronous tasks
27 tasks = [[task, "One", work_queue], [task, "Two", work_queue]]
28
29 # Run the tasks
30 for t, n, q in tasks:
31 t[n, q]
32
33if __name__ == "__main__":
34 main[]
0Bạn có thể thấy rằng cả
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
02 và Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
06 đều đang chạy và sử dụng công việc từ hàng đợi. Đây là mục đích, vì cả hai tác vụ đều đang xử lý công việc và mỗi tác vụ chịu trách nhiệm cho hai mục trong hàng đợi. Điều này thật thú vị, nhưng một lần nữa, phải mất khá nhiều công sức để đạt được những kết quả nàyMẹo ở đây là sử dụng câu lệnh
1import queue
2
3def task[name, work_queue]:
4 if work_queue.empty[]:
5 print[f"Task {name} nothing to do"]
6 else:
7 while not work_queue.empty[]:
8 count = work_queue.get[]
9 total = 0
10 print[f"Task {name} running"]
11 for x in range[count]:
12 total += 1
13 print[f"Task {name} total: {total}"]
14
15def main[]:
16 """
17 This is the main entry point for the program
18 """
19 # Create the queue of work
20 work_queue = queue.Queue[]
21
22 # Put some work in the queue
23 for work in [15, 10, 5, 2]:
24 work_queue.put[work]
25
26 # Create some synchronous tasks
27 tasks = [[task, "One", work_queue], [task, "Two", work_queue]]
28
29 # Run the tasks
30 for t, n, q in tasks:
31 t[n, q]
32
33if __name__ == "__main__":
34 main[]
00, biến Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
5 thành bộ tạo và thực hiện chuyển đổi ngữ cảnh. Chương trình sử dụng công tắc ngữ cảnh này để trao quyền điều khiển cho vòng lặp Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
03 trong Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
7, cho phép hai phiên bản của một tác vụ cùng chạyLưu ý cách
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
06 xuất tổng đầu tiên. Điều này có thể khiến bạn nghĩ rằng các tác vụ đang chạy không đồng bộ. Tuy nhiên, đây vẫn là chương trình đồng bộ. Nó được cấu trúc để hai tác vụ có thể trao đổi ngữ cảnh qua lại. Lý do tại sao Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
06 đưa ra tổng số đầu tiên là vì nó chỉ đếm đến 10, trong khi Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
02 đang đếm đến 15. Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
06 chỉ cần đạt đến tổng số đầu tiên, do đó, nó sẽ in đầu ra của nó ra bàn điều khiển trước Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
02Ghi chú. Tất cả các mã ví dụ tiếp theo từ thời điểm này đều sử dụng một mô-đun có tên là codetiming theo thời gian và xuất ra các đoạn mã mất bao lâu để thực thi. Có một bài viết tuyệt vời ở đây về RealPython đi sâu về mô-đun codetiming và cách sử dụng nó
Mô-đun này là một phần của Chỉ mục gói Python và được xây dựng bởi Geir Arne Hjelle, thành viên của nhóm Real Python. Geir Arne đã giúp tôi rất nhiều trong việc xem xét và gợi ý những điều cho bài viết này. Nếu bạn đang viết mã cần bao gồm chức năng định thời gian, thì mô-đun định thời gian của Geir Arne rất đáng xem
Để cung cấp mô-đun lập mã thời gian cho các ví dụ tiếp theo, bạn cần cài đặt mô-đun này. Điều này có thể được thực hiện với
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
31 bằng lệnh này. Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
32, hoặc với lệnh này. Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
33. Tệp Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
2 là một phần của kho mã ví dụLoại bỏ các quảng cáoĐồng thời hợp tác với các cuộc gọi chặn
Phiên bản tiếp theo của chương trình giống như phiên bản trước, ngoại trừ việc bổ sung một
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
35 trong phần thân của vòng lặp nhiệm vụ của bạn. Điều này thêm độ trễ dựa trên giá trị được lấy từ hàng đợi công việc cho mỗi lần lặp lại của vòng lặp tác vụ. Độ trễ mô phỏng tác động của cuộc gọi chặn xảy ra trong tác vụ của bạnCuộc gọi chặn là mã ngăn CPU làm bất cứ điều gì khác trong một khoảng thời gian. Trong các thử nghiệm tưởng tượng ở trên, nếu cha mẹ không thể thoát khỏi việc cân bằng sổ séc cho đến khi hoàn tất, thì đó sẽ là một cuộc gọi chặn
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
35 làm điều tương tự trong ví dụ này, bởi vì CPU không thể làm gì khác ngoài việc đợi hết thời gian trì hoãnTask One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
4Đây là điểm khác biệt trong đoạn mã trên
- Dòng 1 nhập mô-đun
37 để cấp cho chương trình quyền truy cập vàoTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
38Task One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 3 nhập mã
39 từ mô-đunTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
30Task One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 6 tạo phiên bản
39 được sử dụng để đo thời gian thực hiện cho mỗi lần lặp của vòng lặp tác vụTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 10 bắt đầu phiên bản
32Task One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 11 thay đổi
5 để bao gồm mộtTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
35 để bắt chước độ trễ IO. Điều này thay thế vòng lặpTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
01 đã đếm trongTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
3Task One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 12 dừng phiên bản
32 và xuất thời gian đã trôi qua kể từ khiTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
38 được gọiTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 30 tạo một trình quản lý bối cảnh
39 sẽ xuất ra thời gian đã trôi qua mà toàn bộ vòng lặp while đã thực hiệnTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
Khi bạn chạy chương trình này, bạn sẽ thấy đầu ra sau
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
8Như trước đây, cả
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
02 và Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
06 đều đang chạy, tiêu thụ công việc từ hàng đợi và xử lý nó. Tuy nhiên, ngay cả khi bổ sung độ trễ, bạn có thể thấy rằng đồng thời hợp tác không mang lại cho bạn bất cứ điều gì. Độ trễ dừng quá trình xử lý của toàn bộ chương trình và CPU chỉ đợi độ trễ IO kết thúcĐây chính xác là ý nghĩa của việc chặn mã trong tài liệu Python async. Bạn sẽ nhận thấy rằng thời gian cần thiết để chạy toàn bộ chương trình chỉ là thời gian tích lũy của tất cả các lần trì hoãn. Chạy các nhiệm vụ theo cách này không phải là một chiến thắng
Đồng thời hợp tác với các cuộc gọi không chặn
Phiên bản tiếp theo của chương trình đã được sửa đổi khá nhiều. Nó sử dụng các tính năng không đồng bộ của Python bằng cách sử dụng asyncio/await được cung cấp trong Python 3
Các mô-đun
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
37 và Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
4 đã được thay thế bằng gói Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
84. Điều này cho phép chương trình của bạn truy cập vào chức năng xếp hàng và ngủ thân thiện [không chặn] không đồng bộ. Thay đổi thành Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
5 xác định nó là không đồng bộ với việc bổ sung tiền tố Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
86 trên dòng 4. Điều này cho Python biết rằng hàm sẽ không đồng bộMột thay đổi lớn khác là loại bỏ các câu lệnh
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
35 và 1import queue
2
3def task[name, work_queue]:
4 if work_queue.empty[]:
5 print[f"Task {name} nothing to do"]
6 else:
7 while not work_queue.empty[]:
8 count = work_queue.get[]
9 total = 0
10 print[f"Task {name} running"]
11 for x in range[count]:
12 total += 1
13 print[f"Task {name} total: {total}"]
14
15def main[]:
16 """
17 This is the main entry point for the program
18 """
19 # Create the queue of work
20 work_queue = queue.Queue[]
21
22 # Put some work in the queue
23 for work in [15, 10, 5, 2]:
24 work_queue.put[work]
25
26 # Create some synchronous tasks
27 tasks = [[task, "One", work_queue], [task, "Two", work_queue]]
28
29 # Run the tasks
30 for t, n, q in tasks:
31 t[n, q]
32
33if __name__ == "__main__":
34 main[]
00 và thay thế chúng bằng Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
89. Điều này tạo ra độ trễ không chặn sẽ thực hiện chuyển đổi ngữ cảnh trở lại người gọi Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
7Vòng lặp
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
03 bên trong Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
7 không còn tồn tại. Thay vì Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
03, có một cuộc gọi đến Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
04. Điều này nói với Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
84 hai điều- Tạo hai tác vụ dựa trên
5 và bắt đầu chạy chúngTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Chờ cho cả hai điều này được hoàn thành trước khi di chuyển về phía trước
Dòng cuối cùng của chương trình
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
07 chạy Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
7. Điều này tạo ra cái được gọi là vòng lặp sự kiện]. Vòng lặp này sẽ chạy Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
7, đến lượt nó sẽ chạy hai phiên bản của Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
5Vòng lặp sự kiện là trung tâm của hệ thống không đồng bộ Python. Nó chạy tất cả mã, bao gồm cả
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
7. Khi mã tác vụ đang thực thi, CPU đang bận làm việc. Khi đạt đến, một chuyển đổi ngữ cảnh xảy ra và điều khiển quay trở lại vòng lặp sự kiện. Vòng lặp sự kiện xem xét tất cả các tác vụ đang chờ một sự kiện [trong trường hợp này là thời gian chờ của Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
13] và chuyển quyền kiểm soát cho một tác vụ có sự kiện đã sẵn sàngTask One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
89 không bị chặn đối với CPU. Thay vì đợi hết thời gian trễ, CPU đăng ký một sự kiện ngủ trên hàng đợi tác vụ của vòng lặp sự kiện và thực hiện chuyển ngữ cảnh bằng cách chuyển điều khiển tới vòng lặp sự kiện. Vòng lặp sự kiện liên tục tìm kiếm các sự kiện đã hoàn thành và chuyển điều khiển trở lại tác vụ đang chờ sự kiện đó. Bằng cách này, CPU có thể luôn bận nếu có công việc, trong khi vòng lặp sự kiện giám sát các sự kiện sẽ xảy ra trong tương laiGhi chú. Một chương trình không đồng bộ chạy trong một luồng thực thi. Việc chuyển ngữ cảnh từ phần mã này sang phần mã khác sẽ ảnh hưởng đến dữ liệu hoàn toàn nằm trong tầm kiểm soát của bạn. Điều này có nghĩa là bạn có thể nguyên tử hóa và hoàn thành tất cả quyền truy cập dữ liệu bộ nhớ dùng chung trước khi thực hiện chuyển ngữ cảnh. Điều này đơn giản hóa vấn đề bộ nhớ dùng chung vốn có trong mã luồng
Mã
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
15 được liệt kê bên dướiTask One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
09Đây là điểm khác biệt giữa chương trình này và
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
16- Dòng 1 nhập
84 để có quyền truy cập vào chức năng không đồng bộ của Python. Điều này thay thế việc nhập khẩuTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
37Task One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 2 nhập mã
39 từ mô-đunTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
30Task One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 4 hiển thị thêm từ khóa
86 trước định nghĩaTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
5. Điều này thông báo cho chương trình rằngTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
23 có thể chạy không đồng bộTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 5 tạo phiên bản
39 được sử dụng để đo thời gian thực hiện cho mỗi lần lặp của vòng lặp nhiệm vụTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 9 bắt đầu phiên bản
32Task One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 10 thay thế
35 bằng không chặnTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
13, điều này cũng mang lại quyền kiểm soát [hoặc chuyển ngữ cảnh] trở lại vòng lặp sự kiện chínhTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 11 dừng phiên bản
32 và xuất thời gian đã trôi qua kể từ khiTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
38 được gọiTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 18 tạo
6 không đồng bộ không chặnTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 21 đến 22 đưa công việc vào
6 theo cách không đồng bộ bằng cách sử dụng từ khóaTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
12Task One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 25 tạo một trình quản lý ngữ cảnh
39 sẽ xuất ra thời gian đã trôi qua mà toàn bộ vòng lặp while đã thực hiệnTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 26 đến 29 tạo 2 tác vụ và gộp chúng lại với nhau, vì vậy chương trình sẽ đợi cả 2 tác vụ hoàn thành
- Dòng 32 bắt đầu chương trình chạy không đồng bộ. Nó cũng bắt đầu vòng lặp sự kiện nội bộ
Khi bạn nhìn vào đầu ra của chương trình này, hãy chú ý cách cả
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
02 và Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
06 bắt đầu cùng một lúc, sau đó đợi lệnh gọi IO giảTask One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
3Điều này chỉ ra rằng
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
89 không bị chặn và công việc khác đang được thực hiệnKhi kết thúc chương trình, bạn sẽ nhận thấy tổng thời gian đã trôi qua về cơ bản chỉ bằng một nửa thời gian để
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
16 chạy. Đó là lợi thế của một chương trình sử dụng các tính năng không đồng bộ của Python. Mỗi tác vụ có thể chạy Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
89 cùng một lúc. Tổng thời gian thực hiện của chương trình bây giờ ít hơn tổng thời gian của các phần của nó. Bạn đã thoát khỏi mô hình đồng bộLoại bỏ các quảng cáoCác cuộc gọi HTTP đồng bộ [Chặn]
Phiên bản tiếp theo của chương trình là một bước tiến cũng như một bước lùi. Chương trình đang thực hiện một số công việc thực tế với IO thực bằng cách thực hiện các yêu cầu HTTP tới danh sách URL và nhận nội dung trang. Tuy nhiên, nó hoạt động theo cách chặn [đồng bộ]
Chương trình đã được sửa đổi để nhập mô-đun
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
39 tuyệt vời để thực hiện các yêu cầu HTTP thực tế. Ngoài ra, hàng đợi hiện chứa danh sách URL, thay vì số. Ngoài ra, Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
5 không còn tăng bộ đếm. Thay vào đó, Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
39 lấy nội dung của một URL được truy xuất từ hàng đợi và in thời gian cần thiết để làm như vậyMã
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
42 được liệt kê dưới đâyTask One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
3Đây là những gì đang xảy ra trong chương trình này
- Dòng 2 nhập
39, cung cấp một cách thuận tiện để thực hiện cuộc gọi HTTPTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 3 nhập mã
39 từ mô-đunTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
30Task One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 6 tạo phiên bản
39 được sử dụng để đo thời gian thực hiện cho mỗi lần lặp của vòng lặp tác vụTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 11 bắt đầu phiên bản
32Task One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 12 giới thiệu độ trễ, tương tự như
16. Tuy nhiên, lần này nó gọiTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
49, trả về nội dung của URL được lấy từTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
6Task One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 13 dừng phiên bản
32 và xuất thời gian đã trôi qua kể từ khiTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
38 được gọiTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 23 đến 32 đưa danh sách các URL vào
6Task One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 39 tạo một trình quản lý bối cảnh
39 sẽ xuất ra thời gian đã trôi qua mà toàn bộ vòng lặp while đã thực hiệnTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
Khi bạn chạy chương trình này, bạn sẽ thấy đầu ra sau
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
8Giống như trong các phiên bản trước của chương trình,
1import queue
2
3def task[name, work_queue]:
4 if work_queue.empty[]:
5 print[f"Task {name} nothing to do"]
6 else:
7 while not work_queue.empty[]:
8 count = work_queue.get[]
9 total = 0
10 print[f"Task {name} running"]
11 for x in range[count]:
12 total += 1
13 print[f"Task {name} total: {total}"]
14
15def main[]:
16 """
17 This is the main entry point for the program
18 """
19 # Create the queue of work
20 work_queue = queue.Queue[]
21
22 # Put some work in the queue
23 for work in [15, 10, 5, 2]:
24 work_queue.put[work]
25
26 # Create some synchronous tasks
27 tasks = [[task, "One", work_queue], [task, "Two", work_queue]]
28
29 # Run the tasks
30 for t, n, q in tasks:
31 t[n, q]
32
33if __name__ == "__main__":
34 main[]
00 biến Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
5 thành máy phát điện. Nó cũng thực hiện chuyển đổi ngữ cảnh cho phép thực hiện nhiệm vụ khácMỗi tác vụ nhận một URL từ hàng đợi công việc, truy xuất nội dung của trang và báo cáo mất bao lâu để nhận được nội dung đó
Như trước đây,
1import queue
2
3def task[name, work_queue]:
4 if work_queue.empty[]:
5 print[f"Task {name} nothing to do"]
6 else:
7 while not work_queue.empty[]:
8 count = work_queue.get[]
9 total = 0
10 print[f"Task {name} running"]
11 for x in range[count]:
12 total += 1
13 print[f"Task {name} total: {total}"]
14
15def main[]:
16 """
17 This is the main entry point for the program
18 """
19 # Create the queue of work
20 work_queue = queue.Queue[]
21
22 # Put some work in the queue
23 for work in [15, 10, 5, 2]:
24 work_queue.put[work]
25
26 # Create some synchronous tasks
27 tasks = [[task, "One", work_queue], [task, "Two", work_queue]]
28
29 # Run the tasks
30 for t, n, q in tasks:
31 t[n, q]
32
33if __name__ == "__main__":
34 main[]
00 cho phép cả hai tác vụ của bạn cùng chạy. Tuy nhiên, vì chương trình này đang chạy đồng bộ, mỗi lệnh gọi Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
58 sẽ chặn CPU cho đến khi trang được truy xuất. Lưu ý tổng thời gian cần thiết để chạy toàn bộ chương trình khi kết thúc. Điều này sẽ có ý nghĩa cho ví dụ tiếp theoCuộc gọi HTTP không đồng bộ [Không chặn]
Phiên bản này của chương trình sửa đổi phiên bản trước đó để sử dụng các tính năng không đồng bộ của Python. Nó cũng nhập mô-đun
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
59, là thư viện để thực hiện các yêu cầu HTTP theo kiểu không đồng bộ bằng cách sử dụng Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
84Các tác vụ ở đây đã được sửa đổi để loại bỏ lệnh gọi
1import queue
2
3def task[name, work_queue]:
4 if work_queue.empty[]:
5 print[f"Task {name} nothing to do"]
6 else:
7 while not work_queue.empty[]:
8 count = work_queue.get[]
9 total = 0
10 print[f"Task {name} running"]
11 for x in range[count]:
12 total += 1
13 print[f"Task {name} total: {total}"]
14
15def main[]:
16 """
17 This is the main entry point for the program
18 """
19 # Create the queue of work
20 work_queue = queue.Queue[]
21
22 # Put some work in the queue
23 for work in [15, 10, 5, 2]:
24 work_queue.put[work]
25
26 # Create some synchronous tasks
27 tasks = [[task, "One", work_queue], [task, "Two", work_queue]]
28
29 # Run the tasks
30 for t, n, q in tasks:
31 t[n, q]
32
33if __name__ == "__main__":
34 main[]
00 vì mã để thực hiện lệnh gọi HTTP Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
62 không còn bị chặn nữa. Nó cũng thực hiện chuyển đổi ngữ cảnh trở lại vòng lặp sự kiệnChương trình
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
63 được liệt kê bên dướiTask One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
0Đây là những gì đang xảy ra trong chương trình này
- Dòng 2 nhập thư viện
59, cung cấp cách thức không đồng bộ để thực hiện cuộc gọi HTTPTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 3 nhập mã
39 từ mô-đunTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
30Task One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 5 đánh dấu
5 là một hàm không đồng bộTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 6 tạo phiên bản
39 được sử dụng để đo thời gian thực hiện cho mỗi lần lặp của vòng lặp tác vụTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 7 tạo trình quản lý ngữ cảnh phiên
59Task One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 8 tạo trình quản lý ngữ cảnh phản hồi
59. Nó cũng thực hiện một cuộc gọi HTTPTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
62 tới URL được lấy từTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
6Task One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 11 bắt đầu phiên bản
32Task One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 12 sử dụng phiên để lấy văn bản từ URL không đồng bộ
- Dòng 13 dừng phiên bản
32 và xuất thời gian đã trôi qua kể từ khiTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
38 được gọiTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
- Dòng 39 tạo một trình quản lý bối cảnh
39 sẽ xuất ra thời gian đã trôi qua mà toàn bộ vòng lặp while đã thực hiệnTask One running Task One total: 15 Task One running Task One total: 10 Task One running Task One total: 5 Task One running Task One total: 2 Task Two nothing to do
Khi bạn chạy chương trình này, bạn sẽ thấy đầu ra sau
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
1Hãy xem tổng thời gian đã trôi qua, cũng như thời gian riêng lẻ để nhận nội dung của từng URL. Bạn sẽ thấy rằng thời lượng bằng khoảng một nửa thời gian tích lũy của tất cả các lệnh gọi HTTP
Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
62. Điều này là do các lệnh gọi HTTP Task One running
Task One total: 15
Task One running
Task One total: 10
Task One running
Task One total: 5
Task One running
Task One total: 2
Task Two nothing to do
62 đang chạy không đồng bộ. Nói cách khác, bạn đang tận dụng lợi thế của CPU một cách hiệu quả hơn bằng cách cho phép nó thực hiện nhiều yêu cầu cùng một lúcVì CPU quá nhanh nên ví dụ này có thể tạo nhiều tác vụ bằng số lượng URL. Trong trường hợp này, thời gian chạy của chương trình sẽ là thời gian truy xuất URL chậm nhất
Loại bỏ các quảng cáoSự kết luận
Bài viết này đã cung cấp cho bạn các công cụ cần thiết để bắt đầu biến các kỹ thuật lập trình không đồng bộ thành một phần trong tiết mục của bạn. Sử dụng các tính năng không đồng bộ của Python cho phép bạn kiểm soát theo chương trình khi diễn ra chuyển ngữ cảnh. Điều này có nghĩa là nhiều vấn đề khó khăn hơn mà bạn có thể thấy trong lập trình luồng sẽ dễ giải quyết hơn
Lập trình không đồng bộ là một công cụ mạnh mẽ, nhưng nó không hữu ích cho mọi loại chương trình. Ví dụ, nếu bạn đang viết một chương trình tính số pi đến chữ số thập phân thứ một triệu, thì mã không đồng bộ sẽ không giúp ích gì cho bạn. Loại chương trình đó bị ràng buộc bởi CPU, không có nhiều IO. Tuy nhiên, nếu bạn đang cố gắng triển khai máy chủ hoặc chương trình thực hiện IO [như truy cập tệp hoặc mạng], thì việc sử dụng các tính năng không đồng bộ của Python có thể tạo ra sự khác biệt lớn
Tóm lại, bạn đã học được
- Các chương trình đồng bộ là gì
- Các chương trình không đồng bộ khác nhau như thế nào, nhưng cũng mạnh mẽ và dễ quản lý
- Tại sao bạn có thể muốn viết các chương trình không đồng bộ
- Cách sử dụng các tính năng không đồng bộ tích hợp trong Python
Bạn có thể lấy mã cho tất cả các chương trình ví dụ được sử dụng trong hướng dẫn này
Tải xuống mã. Nhấp vào đây để tải xuống mã mà bạn sẽ sử dụng để tìm hiểu về các tính năng không đồng bộ trong Python trong hướng dẫn này
Bây giờ bạn đã được trang bị những kỹ năng mạnh mẽ này, bạn có thể đưa chương trình của mình lên một tầm cao mới
Đánh dấu là đã hoàn thành
🐍 Thủ thuật Python 💌
Nhận một Thủ thuật Python ngắn và hấp dẫn được gửi đến hộp thư đến của bạn vài ngày một lần. Không có thư rác bao giờ. Hủy đăng ký bất cứ lúc nào. Được quản lý bởi nhóm Real Python
Gửi cho tôi thủ thuật Python »
Giới thiệu về Doug Farrell
Doug là nhà phát triển Python với hơn 25 năm kinh nghiệm. Anh ấy viết về Python trên trang web cá nhân của mình và làm việc với tư cách là Kỹ sư web cấp cao của Shutterfly
» Thông tin thêm về DougMỗi hướng dẫn tại Real Python được tạo bởi một nhóm các nhà phát triển để nó đáp ứng các tiêu chuẩn chất lượng cao của chúng tôi. Các thành viên trong nhóm đã làm việc trong hướng dẫn này là
Aldren
Brad
Geir Arne
Jaya
Joanna
Bậc thầy Kỹ năng Python trong thế giới thực Với quyền truy cập không giới hạn vào Python thực
Tham gia với chúng tôi và có quyền truy cập vào hàng nghìn hướng dẫn, khóa học video thực hành và cộng đồng các Pythonistas chuyên gia
Nâng cao kỹ năng Python của bạn »
Bậc thầy Kỹ năng Python trong thế giới thực
Với quyền truy cập không giới hạn vào Python thực
Tham gia với chúng tôi và có quyền truy cập vào hàng ngàn hướng dẫn, khóa học video thực hành và cộng đồng các chuyên gia Pythonistas
Nâng cao kỹ năng Python của bạn »
Bạn nghĩ sao?
Đánh giá bài viết này
Tweet Chia sẻ Chia sẻ EmailBài học số 1 hoặc điều yêu thích mà bạn đã học được là gì?
Mẹo bình luận. Những nhận xét hữu ích nhất là những nhận xét được viết với mục đích học hỏi hoặc giúp đỡ các sinh viên khác. và nhận câu trả lời cho các câu hỏi phổ biến trong cổng thông tin hỗ trợ của chúng tôi