JEP 444, виртуальные потоки, был повышен с Кандидат к Предлагается для таргетинга статус для JDK 21. Эта функция обеспечивает виртуальные потоки, облегченные потоки, которые значительно сокращают усилия по написанию, обслуживанию и наблюдению за параллельными приложениями с высокой пропускной способностью на платформе Java. Этот JEP предназначен для завершения этой функции на основе отзывов о предыдущих двух раундах предварительной версии: JEP 436, Виртуальные потоки (вторая предварительная версия), представленной в JDK 20; и JEP 425, Виртуальные потоки (предварительная версия), поставляемые в составе JDK 19.
С этим JEP в Java теперь есть два типа потоков: традиционные потоки, также называемые потоками платформы, и виртуальные потоки. Потоки платформы — это индивидуальная оболочка над потоками операционной системы, а виртуальные потоки — это упрощенные реализации, предоставляемые JDK, которые могут запускать множество виртуальных потоков в одном потоке ОС. Виртуальные потоки предлагают более эффективную альтернативу платформенным потокам, позволяя разработчикам выполнять большое количество задач со значительно меньшими затратами. Эти потоки обеспечивают совместимость с существующим кодом Java и беспрепятственный путь миграции, позволяющий повысить производительность и использование ресурсов. Рассмотрим следующий пример:
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, 10_000).forEach(i -> {
executor.submit(() -> {
Thread.sleep(Duration.ofSeconds(1));
return i;
});
});
}
Теперь JDK может запускать до 10 000 одновременных виртуальных потоков в небольшом количестве потоков операционной системы (ОС), всего один, для выполнения приведенного выше простого кода, который требует ожидания в течение одной секунды.
Виртуальные потоки предназначены для работы с локальными переменными потока и наследуемыми локальными переменными потока, как и потоки платформы. Однако из-за большого количества виртуальных потоков, которые можно создать, разработчикам следует с осторожностью использовать локальные переменные потока. Чтобы облегчить переход к виртуальным потокам, JDK предоставляет системное свойство, jdk.traceVirtualThreadLocals
который запускает трассировку стека, когда виртуальный поток устанавливает значение любой локальной переменной потока.
java.util.concurrent
package теперь включает поддержку виртуальных потоков. LockSupport
API был обновлен для изящной парковки и разпарковки виртуальных потоков, что позволяет API, использующим LockSupport
, такие как блокировки, семафоры и очереди блокировки, для беспрепятственной работы с виртуальными потоками. Executors.newThreadPerTaskExecutor(ThreadFactory)
и Executors.newVirtualThreadPerTaskExecutor()
методы обеспечивают ExecutorService
который создает новый поток для каждой задачи, облегчая миграцию и взаимодействие с существующим кодом, который использует пулы потоков и ExecutorService
.
Сетевые API в java.net
и java.nio.channels
пакеты теперь поддерживают виртуальные потоки, повышая эффективность параллельных приложений. Блокирующие операции в виртуальном потоке освобождают базовый поток платформы, в то время как методы ввода/вывода в виртуальном потоке Socket
, ServerSocket
и DatagramSocket
занятия сделали прерываемыми. Это обновление способствует согласованному поведению и повышению производительности для разработчиков Java, работающих с параллельными приложениями.
java.io
Пакет, который предоставляет API для потоков байтов и символов, был обновлен, чтобы избежать закрепления при использовании в виртуальных потоках. Закрепление в виртуальных потоках означает, что облегченный поток «застревает» в конкретном потоке платформы, что ограничивает параллелизм и гибкость из-за блокирующих операций. BufferedInputStream
, BufferedOutputStream
, BufferedReader
, BufferedWriter
, PrintStream
и PrintWriter
теперь используйте явную блокировку вместо монитора при прямом использовании. Потоковые декодеры и кодеры, используемые InputStreamReader
и OutputStreamWriter
теперь используйте тот же замок, что и их закрывающий InputStreamReader
или OutputStreamWriter
.
Java Native Interface (JNI) представил новую функцию, IsVirtualThread
, чтобы проверить, является ли объект виртуальным потоком. В остальном спецификация JNI остается неизменной.
Архитектура отладки, состоящая из интерфейса инструментов JVM (JVM TI), проводного протокола отладки Java (JDWP) и интерфейса отладки Java (JDI), была обновлена для поддержки виртуальных потоков. Все три интерфейса теперь поддерживают виртуальные потоки с добавлением новых возможностей и методов для обработки событий начала и окончания потока, а также массовой приостановки и возобновления виртуальных потоков.
JDK Flight Recorder (JFR) теперь поддерживает виртуальные потоки с новыми событиями, такими как jdk.VirtualThreadStart
, jdk.VirtualThreadEnd
, jdk.VirtualThreadPinned
и jdk.VirtualThreadSubmitFailed
. Эти события дают представление о поведении виртуальных потоков в приложении.
Расширения управления Java (JMX) по-прежнему будут поддерживать только потоки платформы через ThreadMXBean
интерфейс. Новый метод в HotSpotDiagnosticsMXBean
Интерфейс создает дамп потока в новом стиле для поддержки виртуальных потоков.
Хотя виртуальные потоки значительно повышают производительность, разработчики должны помнить о рисках совместимости из-за изменений в существующих API и их реализациях. Некоторые из этих рисков включают изменения протокола внутренней блокировки в java.io
несовместимые с пакетом и исходным кодом, а также двоичные файлы, которые могут повлиять на код, расширяющий Thread
сорт.
Виртуальные потоки знаменуют собой важную веху на пути Java к поддержке высокопараллельных и масштабируемых приложений. Благодаря более эффективной и облегченной модели многопоточности разработчики теперь могут легко справляться с миллионами задач и лучше использовать системные ресурсы. Разработчики могут воспользоваться более подробной информацией о JEP 425, которую можно найти в этом выпуске новостей InfoQ и в этой экранной демонстрации JEP Café Хосе Помара, защитника Java-разработчиков из группы Java Platform Group в Oracle.