# ===== CodeLab: Python 并发编程:线程与协程 =====
# 来源: https://aoerliang.dpdns.org/articles/python-concurrency
# 以下代码片段按文章出现顺序拼接, 共 5 段

# ----- 片段 1 (python) -----
import threading, time

def worker(name):
    print(f"{name} 开始")
    time.sleep(1)
    print(f"{name} 结束")

t = threading.Thread(target=worker, args=("A",))
t.start()
t.join()          # 等待线程结束
print("主线程继续")

# ----- 片段 2 (python) -----
from concurrent.futures import ThreadPoolExecutor
import time

def fetch(url):
    time.sleep(0.5)          # 模拟网络请求
    return f"OK: {url}"

urls = [f"https://x.com/{i}" for i in range(8)]
with ThreadPoolExecutor(max_workers=4) as pool:
    results = list(pool.map(fetch, urls))
print(results)

# ----- 片段 3 (python) -----
import threading

counter = 0
lock = threading.Lock()

def add():
    global counter
    for _ in range(100_000):
        with lock:            # 同一时刻只有一个线程能进入
            counter += 1

ts = [threading.Thread(target=add) for _ in range(4)]
[t.start() for t in ts]
[t.join() for t in ts]
print(counter)   # 400000;不加锁结果可能不对

# ----- 片段 4 (python) -----
import asyncio

async def hello(name):
    print(f"开始 {name}")
    await asyncio.sleep(1)     # 模拟 IO,让出控制权
    print(f"完成 {name}")

async def main():
    await asyncio.gather(
        hello("A"), hello("B"), hello("C"),
    )

asyncio.run(main())   # 三个任务总耗时约 1 秒

# ----- 片段 5 (python) -----
import asyncio, aiohttp

async def fetch(session, url):
    async with session.get(url) as resp:
        return await resp.text()

async def main():
    async with aiohttp.ClientSession() as session:
        tasks = [fetch(session, f"https://httpbin.org/get?i={i}")
                 for i in range(10)]
        results = await asyncio.gather(*tasks)
    print("完成", len(results), "个请求")

asyncio.run(main())
