Thread и Runnable
Тема дорожной карты · Java
Потоки в Java — это фундаментальная единица конкурентного выполнения на JVM, представляющая независимый путь потока программы, который операционная система планирует на доступных ядрах CPU, позволяя Java-приложениям выполнять несколько задач одновременно. Класс Thread и интерфейс Runnable образуют классический API конкурентности: потоки создаются путём наследования от Thread или передачи Runnable (или Lambda-выражения) в new Thread(task), и управляются через start(), sleep(millis), join(), interrupt() и мониторный протокол wait()/notify() для межпоточного взаимодействия. Современная Java Concurrency отдаёт предпочтение высокоуровневому фреймворку java.util.concurrent перед прямым использованием потоков: ExecutorService и ThreadPoolExecutor управляют жизненным циклом пула потоков, Callable<T> и Future<T> представляют асинхронные результаты, а CompletableFuture обеспечивает неблокирующие, компонуемые асинхронные конвейеры с thenApply, thenCompose и exceptionally. Project Loom в Java 21 ввёл Virtual Threads (Thread.ofVirtual().start(task)) — лёгкие JVM-управляемые потоки, разделяющие потоки-носители платформы, — позволяя создавать миллионы конкурентных потоков без накладных расходов на создание потоков ОС и трансформируя масштабирование I/O-ёмких Spring и JDBC-нагрузок. Понимание жизненного цикла Java-потока (NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED), правил happens-before Java Memory Model, synchronized, volatile и java.util.concurrent.locks является фундаментом для написания корректных, свободных от взаимоблокировок и производительных конкурентных Java-приложений.
Как это работает
Thread и Runnable имеет много инструментов: Thread (низкоуровневый), Executor / ExecutorService (пулы потоков), CompletableFuture (async-композиция), Future, java.util.concurrent коллекции (ConcurrentHashMap, BlockingQueue, CopyOnWriteArrayList), атомарные примитивы (AtomicInteger, AtomicReference). Java 21 даёт virtual threads (Project Loom — миллионы лёгких потоков, идеально для I/O-bound). Синхронизация: synchronized, ReentrantLock, ReadWriteLock, StampedLock. Memory model (JMM) управляет видимостью.
Когда применять
ExecutorService вместо сырых Thread — пулы управляют жизненным циклом. CompletableFuture — для async-композиции (thenApply, thenCompose, allOf). На Java 21+ virtual threads делают блокирующий I/O практичным на высокой конкурентности (Executors.newVirtualThreadPerTaskExecutor()). ConcurrentHashMap — для shared-state. Прочтите "Java Concurrency in Practice" до серьёзного concurrent-кода.
Типичные ошибки
Ловушки Thread и Runnable: shared mutable state без синхронизации (visibility-баги); volatile-"фикс" для race, требующих атомарности (volatile только видимость, не атомарный RMW); deadlock из-за двух локов в разном порядке; не daemon-threads когда нужно (JVM висит при shutdown); слишком много потоков для I/O-bound до Loom (новый ответ — virtual threads).