پاسخ تمرین ۱
این پارامتر حداکثر تعداد تردهایی را که میتوانند در یک لحظه همزمان اجرا شوند مشخص میکند؛ کارهای بیشتر در صف میمانند تا یک ترد آزاد شود.
پاسخ تمرین ۲
چون آن executor فقط اجازهی اجرای همزمان دو ترد را داده (max_workers=2)؛ پس سومین تسک باید منتظر بماند تا یکی از دو تسک در حال اجرا به پایان برسد و یک ترد آزاد شود.
پاسخ تمرین ۳
executor.map برای اعمال سریع یک تابع روی یک لیست ورودی مناسب است، اما executor.submit هر تسک را تکبهتک ارسال میکند و یک شیء Future برمیگرداند که بعداً میتوانیم از آن استفاده کنیم.
پاسخ تمرین ۴
با فراخوانی future.result() روی هر Futureای که از submit برگشته، مقدار بازگشتی تسک را میگیریم.
پاسخ تمرین ۵
import time
from concurrent.futures import ThreadPoolExecutor
def task(name):
print(f"Task {name} started")
time.sleep(1)
print(f"Task {name} finished")
with ThreadPoolExecutor(max_workers=2) as executor:
executor.map(task, [1, 2, 3, 4, 5])چون max_workers=2 است، فقط دو ترد در استخر وجود دارد؛ پس در هر لحظه حداکثر دو کار اجرا میشود و کار بعدی تا آزادشدن یک ترد شروع نمیشود.
پاسخ تمرین ۶
import time
from concurrent.futures import ThreadPoolExecutor
def task(name):
time.sleep(1)
return f"Result of task {name}"
with ThreadPoolExecutor(max_workers=2) as executor:
futures = [executor.submit(task, i) for i in [1, 2, 3, 4]]
results = [future.result() for future in futures]
print("Results:", results)پاسخ تمرین ۷
import time
from concurrent.futures import ThreadPoolExecutor
def fetch(url):
time.sleep(2)
return f"{url} done"
urls = [f"site{i}.com" for i in range(8)]
start = time.time()
with ThreadPoolExecutor(max_workers=8) as executor:
results = list(executor.map(fetch, urls))
print("took %.1fs" % (time.time() - start)) # ~2s, not ~16sچون هر ترد بیشترِ وقت منتظر شبکه است و ۸ کارگر داریم، هر هشت دانلود عملاً همزمان پیش میروند و کل کار حدود ۲ ثانیه (بهجای ۱۶ ثانیه) طول میکشد.
پاسخ تمرین ۸
برای کارهای I/O-bound (شبکه، فایل، دیتابیس) از ThreadPoolExecutor و برای کارهای CPU-bound (محاسبات سنگین) از ProcessPoolExecutor استفاده کنید. تردها برای CPU-bound مناسب نیستند چون GIL اجازهی اجرای موازیِ واقعیِ کدِ پایتون را نمیدهد؛ پس چند ترد در محاسبات سنگین سریعتر از یک ترد نمیشوند و باید از پردازهها (که هرکدام GIL مستقل دارند) استفاده کرد.