Поток (Thread) – минимальная единица выполнения программы (последовательность команд).
Каждый поток выполняется независимо от других, может идти параллельно или псевдопараллельно (через планировщик потоков операционной системы).
Многопоточность позволяет выполнять несколько задач одновременно, используя несколько ядер процессора или чередуя выполнение задач на одном ядре.
В Java поток представляется классом Thread или задаваем через интерфейс Runnable (объект Thread запускает код интерфейса Runnable).
Пояснение:
Поток (thread) – это независимая последовательность команд внутри программы, которая может выполняться одновременно с другими потоками. В контексте операционной системы каждый поток обычно сопоставляется с нитями выполнения, управляемыми планировщиком (scheduler). Если у компьютера несколько ядер, потоки действительно могут выполняться параллельно (одновременно на разных ядрах); на одном ядре потоки работают псевдопараллельно, быстро сменяя друг друга по расписанию, создавая иллюзию одновременности. Использование нескольких потоков позволяет программе более эффективно использовать ресурсы системы и не блокировать выполнение при ожидании операций ввода-вывода – например, один поток может ждать загрузки данных из сети, пока другой продолжает вычисления.
В Java каждый поток представлен объектом класса Thread. Чтобы запустить новую ветку выполнения, достаточно создать объект Thread и вызвать у него метод start(). Однако класс Thread – не единственный способ задания кода потока. Чаще применяют интерфейс Runnable: вы создаете класс или лямбда-выражение, реализующее метод run(), и передаете его в конструктор Thread. Например:
Runnable task = () -> System.out.println("Hello from thread!");Thread thread = new Thread(task);
thread.start();
Метод start() создаст новый поток и выполнит код run() в этом потоке. Если же вызвать метод run() напрямую (например, thread.run()), никакого нового потока не возникнет – код выполнится в текущем потоке, поэтому всегда нужно вызывать start(), а не run() для параллельности.
Важно отметить, что потоки одной программы разделяют общую память процесса. Все глобальные переменные, объекты в куче и т.д. доступны всем потокам. Это облегчает обмен данными между потоками, но приводит к проблеме состояний гонки (race conditions) – ситуации, когда несколько потоков одновременно обращаются к одним и тем же данным и могут нарушать логику друг друга. Для безопасной работы с общими данными Java предоставляет механизмы синхронизации (см. раздел про синхронизацию ниже).
Современные подходы в Java-разработке рекомендуют не создавать потоки вручную для каждой задачи, а пользоваться более высокоуровневыми возможностями. В стандартной библиотеке, начиная с Java 5, появился фреймворк Executors – он управляет пулом потоков и позволяет запускать задачи параллельно, не работая напрямую с классом Threadjava-online.rujava-online.ru. Например, вместо многочисленных new Thread(...).start() вы можете использовать ExecutorService для выполнения задач, и он сам будет переиспользовать ограниченное количество потоков:
ExecutorService executor = Executors.newFixedThreadPool(4);for (int i = 0; i < 10; i++) {
executor.submit(() -> {
// код задачи, выполняемый в пуле потоков
});
}
executor.shutdown();
Такой подход экономнее расходует ресурсы и упрощает управление потоками (например, можно аккуратно завершить все задачи методом shutdown() и дождаться их окончания). Важно: несмотря на появление высокого уровня абстракций, понимание работы потоков и низкоуровневых примитивов остается необходимым. Кроме того, с выходом Java 19+ появились виртуальные потоки – чрезвычайно легкие потоки, реализованные внутри JVM (проект Loom). Они позволяют создавать тысячи и миллионы потоков с минимальными накладными расходами, упрощая написание высоконагруженных многопоточных приложенийopenjdk.org. Виртуальные потоки поддерживают тот же API Thread, но планируются не напрямую операционной системой, а виртуальной машиной Java, что снимает ограничения на количество одновременно работающих нитей. Благодаря этому современная Java позволяет писать код в привычном стиле «один запрос – один поток» без потери масштабируемости.
