Ответ
В Python для реализации многопоточности, в основном для I/O-bound задач, используются инструменты из стандартной библиотеки. Главным ограничением является Global Interpreter Lock (GIL), который не позволяет нескольким потокам одновременно выполнять Python байт-код на многоядерных CPU.
1. Модуль threading
Это низкоуровневый модуль для прямого управления потоками.
threading.Thread: Основной класс для создания потока.- Примитивы синхронизации:
Lock,RLock,Semaphore,Eventдля предотвращения состояний гонки (race conditions) при доступе к общим данным.
Пример:
import threading
import time
def worker(name):
print(f"Поток {name} начал работу")
time.sleep(1)
print(f"Поток {name} завершил работу")
threads = []
for i in range(3):
# Создаем и запускаем поток
t = threading.Thread(target=worker, args=(i,))
threads.append(t)
t.start()
# Ожидаем завершения всех потоков
for t in threads:
t.join()
print("Все потоки завершены")
2. Модуль concurrent.futures
Это высокоуровневый интерфейс для асинхронного выполнения задач, который упрощает работу с пулами потоков.
ThreadPoolExecutor: Управляет пулом потоков, автоматически распределяя задачи.
Пример:
import concurrent.futures
import time
def worker(name):
time.sleep(1)
return f"Результат от потока {name}"
# Создаем пул из 3 потоков
with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
# Отправляем задачи на выполнение
futures = [executor.submit(worker, i) for i in range(3)]
# Получаем результаты по мере готовности
for future in concurrent.futures.as_completed(futures):
print(future.result())
Вывод:
- Используйте
threadingдля полного контроля над жизненным циклом потоков и сложной синхронизации. - Используйте
concurrent.futures.ThreadPoolExecutorдля более простых задач, где нужно просто выполнить набор функций в отдельных потоках и получить результат.
Ответ 18+ 🔞
А, ну ты про потоки в питоне, да? Ну это, блядь, классика жанра, как Герасим с Муму, только с кодом. Слушай сюда, сейчас разжую.
Так вот, в питоне, если тебе надо, чтобы несколько дел одновременно делалось — типа файлы качать или запросы в сеть слать — тебе на потоки. Но тут есть одна, сука, засада — Global Interpreter Lock (GIL). Эта, блядь, штука, как ревнивая баба, не даёт нескольким потокам одновременно Python-код исполнять на всех ядрах процессора. То есть, по сути, они друг другу мешают, очередь выстраивают. Для вычислений, где мозги нужны (CPU-bound), это пиздец как неэффективно, а вот для дел, где ты в основном ждёшь (I/O-bound) — самое то.
1. Модуль threading — это как вручную всё делать
Низкоуровневый такой, для тех, кто любит поковыряться. Тут тебе и потоки создавать, и замки на них вешать, чтобы они друг у друга из-под носа данные не воровали.
Смотри, как это выглядит:
import threading
import time
def worker(name):
print(f"Поток {name} начал работу")
time.sleep(1) # Притворяется, что работает, а сам спит, ленивая жопа
print(f"Поток {name} завершил работу")
threads = []
for i in range(3):
# Рождаем поток, как Герасим Муму нашёл
t = threading.Thread(target=worker, args=(i,))
threads.append(t)
t.start() # И пускаем в свободное плавание
# А теперь ждём, пока все эти твари закончат
for t in threads:
t.join() # Стоим, как дураки, и ждём
print("Все потоки завершены")
Вот тут ты сам за всё отвечаешь: запустил, подождал, замок на дверь повесил, если надо. Сам себе режиссёр, оператор и Герасим.
2. Модуль concurrent.futures — для ленивых и умных
Это уже высший пилотаж, ёпта. Тебе не надо возиться с каждой ниткой по отдельности. Ты создаёшь пул — типа бригаду грузчиков — и кидаешь им задачи. Они сами разберутся.
Вот, смотри, как элегантно:
import concurrent.futures
import time
def worker(name):
time.sleep(1)
return f"Результат от потока {name}" # Вернул и молодец
# Создаём пул из трёх работяг
with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
# Кидаем им три задания, как кости собаке
futures = [executor.submit(worker, i) for i in range(3)]
# А теперь собираем урожай, что созрело
for future in concurrent.futures.as_completed(futures):
print(future.result()) # Достаём результат, как из кармана
*Итог, чтобы не ебть себе мозг:**
threading— бери, если тебе надо, блядь, полный контроль, сложные танцы с замками и событиями. Сам всё делаешь, сам и отвечаешь.concurrent.futures.ThreadPoolExecutor— бери, если тебе просто кучу похожих задач выполнить, а результат собрать. Красота, а не инструмент. Не надо изобретать велосипед, всё уже придумали до нас, пидарасы умные.
Вот и вся философия. Выбирай, что тебе ближе по душе, и не загоняйся. Главное — GIL не забывай, а то будешь как Герасим, который немой: хочешь сказать, а нихуя не получается.