ForkJoinPool, ExecutorService и Virtual Threads: что выбирать в Java?
Всё зависит от нагрузки: задачи в основном вычисляют или ждут ответа базы и внешних сервисов? При этом сравниваются разные уровни: ExecutorService — интерфейс управления задачами, ForkJoinPool — одна из его реализаций, а виртуальные потоки — тип потоков. Их можно использовать вместе.
ForkJoinPool — для параллельных вычислений. Хорошо подходит для задач, которые можно разбить на независимые части: рекурсивных алгоритмов, обработки массивов и других CPU-intensive вычислений.
Использует work-stealing: свободный рабочий поток забирает задачи из очередей других потоков. Но не любая тяжёлая операция требует ForkJoinPool. Для независимых вычислительных задач может быть достаточно обычного фиксированного пула.
ExecutorService — для запуска и управления задачами. Позволяет отправлять задачи на выполнение, получать результаты через
Здесь одновременно работают не более 10 потоков. Однако очередь задач у такого исполнителя не ограничена: при постоянной перегрузке она может расти. Для выполнения по расписанию используется
Virtual Threads — для большого количества ожидающих задач. Виртуальные потоки стали стандартной возможностью в Java 21. Они особенно полезны, когда задачи много времени проводят в блокирующих вызовах к БД или HTTP-сервисам. Их тоже можно использовать через
Каждая задача получает отдельный виртуальный поток. Создавать пул для переиспользования виртуальных потоков не нужно.
Что важно в продакшене:
• Виртуальные потоки не добавляют процессорных ядер и сами по себе не ускоряют вычисления.
• Тысячи виртуальных потоков не означают, что база выдержит тысячи одновременных запросов. Нужны отдельные ограничения, например пул соединений или
• Ограничение числа рабочих потоков не равно ограничению очереди задач.
ForkJoinPool помогает распараллеливать вычисления. ExecutorService управляет выполнением задач. Virtual Threads позволяют эффективно организовать множество задач, ожидающих I/O.
👉 Java Portal
Всё зависит от нагрузки: задачи в основном вычисляют или ждут ответа базы и внешних сервисов? При этом сравниваются разные уровни: ExecutorService — интерфейс управления задачами, ForkJoinPool — одна из его реализаций, а виртуальные потоки — тип потоков. Их можно использовать вместе.
ForkJoinPool — для параллельных вычислений. Хорошо подходит для задач, которые можно разбить на независимые части: рекурсивных алгоритмов, обработки массивов и других CPU-intensive вычислений.
Использует work-stealing: свободный рабочий поток забирает задачи из очередей других потоков. Но не любая тяжёлая операция требует ForkJoinPool. Для независимых вычислительных задач может быть достаточно обычного фиксированного пула.
ExecutorService — для запуска и управления задачами. Позволяет отправлять задачи на выполнение, получать результаты через
Future и управлять завершением исполнителя. Конкретная реализация определяет, как выполняются задачи.ExecutorService executor =
Executors.newFixedThreadPool(10);
Здесь одновременно работают не более 10 потоков. Однако очередь задач у такого исполнителя не ограничена: при постоянной перегрузке она может расти. Для выполнения по расписанию используется
ScheduledExecutorService.Virtual Threads — для большого количества ожидающих задач. Виртуальные потоки стали стандартной возможностью в Java 21. Они особенно полезны, когда задачи много времени проводят в блокирующих вызовах к БД или HTTP-сервисам. Их тоже можно использовать через
ExecutorService:try (var executor =
Executors.newVirtualThreadPerTaskExecutor()) {
executor.submit(() -> callExternalApi());
}
Каждая задача получает отдельный виртуальный поток. Создавать пул для переиспользования виртуальных потоков не нужно.
Что важно в продакшене:
• Виртуальные потоки не добавляют процессорных ядер и сами по себе не ускоряют вычисления.
• Тысячи виртуальных потоков не означают, что база выдержит тысячи одновременных запросов. Нужны отдельные ограничения, например пул соединений или
Semaphore.• Ограничение числа рабочих потоков не равно ограничению очереди задач.
ForkJoinPool помогает распараллеливать вычисления. ExecutorService управляет выполнением задач. Virtual Threads позволяют эффективно организовать множество задач, ожидающих I/O.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3
Откуда в Spring Boot берётся веб-сервер?
Запускаете приложение:
И оно начинает принимать HTTP-запросы. Без отдельной установки Tomcat и развёртывания WAR-файла.
Секрет — во встроенном сервере. Для обычного Spring MVC-приложения зависимость веб-стартера по умолчанию подтягивает Tomcat. Его библиотеки входят в исполняемый JAR, а Spring Boot автоматически настраивает и запускает сервер вместе с приложением.
Это упрощает запуск и развёртывание: приложение и сервер поставляются как единое целое, с согласованными версиями и настройками. Такой JAR удобно запускать локально, на сервере или в контейнере.
Embedded не означает, что сервера нет. Он работает внутри процесса вашего Java-приложения. Tomcat — не единственный вариант: например, приложения на Spring WebFlux по умолчанию используют Reactor Netty.
👉 Java Portal
Запускаете приложение:
java -jar app.jar
И оно начинает принимать HTTP-запросы. Без отдельной установки Tomcat и развёртывания WAR-файла.
Секрет — во встроенном сервере. Для обычного Spring MVC-приложения зависимость веб-стартера по умолчанию подтягивает Tomcat. Его библиотеки входят в исполняемый JAR, а Spring Boot автоматически настраивает и запускает сервер вместе с приложением.
Это упрощает запуск и развёртывание: приложение и сервер поставляются как единое целое, с согласованными версиями и настройками. Такой JAR удобно запускать локально, на сервере или в контейнере.
Embedded не означает, что сервера нет. Он работает внутри процесса вашего Java-приложения. Tomcat — не единственный вариант: например, приложения на Spring WebFlux по умолчанию используют Reactor Netty.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤3
Как менялись языки программирования
Каждое поколение языков помогало решать новые задачи: от управления железом до разработки веб-приложений и распределённых систем.
История по десятилетиям появления:
• 1940-е: машинный код и первые ассемблеры.
• 1950-е: FORTRAN, Lisp, COBOL.
• 1960-е: BASIC.
• 1970-е: C, Pascal.
• 1980-е: C++, Objective-C.
• 1990-е: Python, Ruby, Java, JavaScript, PHP.
• 2000-е: C#, Scala, Go.
• 2010-е: Rust, Kotlin, Swift.
2020-е — распространение разработки с AI-помощниками. Это уже изменение способа работы с кодом, а не отдельное поколение языков.
Новые инструменты не делают старые языки ненужными. C остаётся важным для операционных систем, Java — для корпоративных приложений, JavaScript — для веба, Python — для анализа данных и машинного обучения.
А на каком языке вы написали свой первый Hello, World?
👉 Java Portal
Каждое поколение языков помогало решать новые задачи: от управления железом до разработки веб-приложений и распределённых систем.
История по десятилетиям появления:
• 1940-е: машинный код и первые ассемблеры.
• 1950-е: FORTRAN, Lisp, COBOL.
• 1960-е: BASIC.
• 1970-е: C, Pascal.
• 1980-е: C++, Objective-C.
• 1990-е: Python, Ruby, Java, JavaScript, PHP.
• 2000-е: C#, Scala, Go.
• 2010-е: Rust, Kotlin, Swift.
2020-е — распространение разработки с AI-помощниками. Это уже изменение способа работы с кодом, а не отдельное поколение языков.
Новые инструменты не делают старые языки ненужными. C остаётся важным для операционных систем, Java — для корпоративных приложений, JavaScript — для веба, Python — для анализа данных и машинного обучения.
А на каком языке вы написали свой первый Hello, World?
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3
Please open Telegram to view this post
VIEW IN TELEGRAM
🤣5
Как HashMap устроен внутри
• Вычисляет хеш ключа.
• Определяет индекс корзины во внутреннем массиве.
• Сохраняет запись в узле с хешем, ключом и значением.
• При коллизиях использует связный список, а начиная с Java 8 при определённых условиях преобразует его в красно-чёрное дерево.
Если такой ключ уже существует,
👉 Java Portal
• Вычисляет хеш ключа.
• Определяет индекс корзины во внутреннем массиве.
• Сохраняет запись в узле с хешем, ключом и значением.
• При коллизиях использует связный список, а начиная с Java 8 при определённых условиях преобразует его в красно-чёрное дерево.
Если такой ключ уже существует,
put() заменяет его значение.Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
Java, Spring Boot, React, микросервисы… А чем веб-сервер отличается от сервера приложений?
У кандидата в резюме несколько full-stack проектов и внушительный стек. Но простой вопрос на собеседовании поставил его в тупик.
• Веб-сервер принимает HTTP-запросы, отдаёт статические файлы и может перенаправлять запросы приложению как reverse proxy. Примеры: Nginx, Apache HTTP Server.
• Сервер приложений предоставляет среду для выполнения приложения и его бизнес-логики. В экосистеме Java примеры — WildFly и Payara.
При этом граница не строгая: сервер приложений может сам принимать HTTP-запросы. Например, Spring Boot со встроенным Tomcat способен обслуживать их без отдельного Nginx, хотя Tomcat точнее называть контейнером сервлетов.
Собрать проект из десяти технологий полезно. Понимать, за что отвечает каждая, — не менее важно.
👉 Java Portal
У кандидата в резюме несколько full-stack проектов и внушительный стек. Но простой вопрос на собеседовании поставил его в тупик.
• Веб-сервер принимает HTTP-запросы, отдаёт статические файлы и может перенаправлять запросы приложению как reverse proxy. Примеры: Nginx, Apache HTTP Server.
• Сервер приложений предоставляет среду для выполнения приложения и его бизнес-логики. В экосистеме Java примеры — WildFly и Payara.
При этом граница не строгая: сервер приложений может сам принимать HTTP-запросы. Например, Spring Boot со встроенным Tomcat способен обслуживать их без отдельного Nginx, хотя Tomcat точнее называть контейнером сервлетов.
Собрать проект из десяти технологий полезно. Понимать, за что отвечает каждая, — не менее важно.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
3 бесплатных ресурса для изучения Java
• Effective Java — конспект — основные идеи книги Джошуа Блоха о том, как писать качественный Java-код.
• Java Design Patterns — паттерны проектирования с объяснениями и примерами реализации на Java.
• Подготовка к собеседованиям — алгоритмы, структуры данных и примеры решений на Java.
Сохраняйте, чтобы вернуться к практике
👉 Java Portal
• Effective Java — конспект — основные идеи книги Джошуа Блоха о том, как писать качественный Java-код.
• Java Design Patterns — паттерны проектирования с объяснениями и примерами реализации на Java.
• Подготовка к собеседованиям — алгоритмы, структуры данных и примеры решений на Java.
Сохраняйте, чтобы вернуться к практике
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4
Java-совет: делайте строки понятнее с String.format()
Если сообщение состоит из множества фрагментов и переменных, шаблон может быть удобнее цепочки
✅ Шаблон отделён от значений.
✅ Проще менять структуру сообщения и добавлять поля.
✅ Для локализуемых сообщений с числами и датами пригодится
Для простых строк конкатенация вполне уместна: выбирайте форматирование ради читаемости, а не скорости.
👉 Java Portal
Если сообщение состоит из множества фрагментов и переменных, шаблон может быть удобнее цепочки
+:String message = String.format(
"Пользователь %s оформил %d заказов",
name, orderCount
);
✅ Шаблон отделён от значений.
✅ Проще менять структуру сообщения и добавлять поля.
✅ Для локализуемых сообщений с числами и датами пригодится
MessageFormat.Для простых строк конкатенация вполне уместна: выбирайте форматирование ради читаемости, а не скорости.
Please open Telegram to view this post
VIEW IN TELEGRAM