Рубрики
Без рубрики

Отличные вещи маячат на горизонте для Java

Почти два года назад я работал в Oracle Code One в Сан-Франциско. Именно там я впервые услышал… С тегами java, project loom, jdk.

Почти два года назад я работал в Oracle Code One в Сан-Франциско. Именно там я впервые услышал о Project Loon, проекте, который должен был внедрить какой-то новый способ параллелизма в Java. На тот момент Loom был всего лишь концепцией, обещанием упростить параллелизм в Java.

Перенесемся на сегодняшний день, и внешний вид немного изменился с момента той первоначальной презентации. Время наверстать упущенное с проектом Look.

Старый выбор иногда причиняет боль в Java

Начиная с Java 1.0 у нас был класс Thread . Этот класс представляет собой представление ресурса операционной системы, а именно потока операционной системы. Потоки операционной системы ограничены парой тысяч одновременно. 25 лет назад это не было большой проблемой. Однако сейчас это огромная проблема, когда некоторым приложениям необходимо обрабатывать десятки тысяч запросов (или больше) одновременно.

Связывая то, что может быть сделано одновременно в Java, с потоками операционной системы, Java чрезвычайно ограничила свою собственную масштабируемость. Чтобы усугубить проблему: изготовление нитей обходится дорого. Просто создавать их для одного запуска и снова утилизировать нецелесообразно. Вот почему мы начали использовать пулы потоков, группы повторно используемых потоков, которые мы поддерживаем в наших приложениях.

Настоящие проблемы начинаются, когда нам приходится блокировать поток . Это происходит всякий раз, когда мы выполняем вызов API, подключаемся к базе данных или читаем из файла. В такие моменты наш поток ничего не делает. Это просто “ожидание” чего-то. Поскольку потоки являются дорогостоящими И ограниченными, это становится серьезным узким местом, если мы хотим получить максимальную отдачу от нашего оборудования.

Ищите спасения

Итак, что же принесет нам проект Loom?

Обратная совместимость

Когда Loom был впервые представлен, мы также познакомились с концепцией Fibers , новой концепцией, которая получила название “Пересмотренные нити”. Это вызвало небольшую полемику в сообществе Java, поскольку росло беспокойство по поводу замены Thread.class везде по Fiber.class , что потребовало бы изменения большого количества кода. По мере развития проекта команда Java поняла, что если он выглядит как поток и работает как поток, то, возможно, это должен быть просто поток!

Вот что они сделали. Вместо того, чтобы создавать совершенно новую концепцию, книга знакомит нас с Виртуальными потоками . В отличие от текущей реализации Thread , виртуальные потоки больше не являются индивидуальным сопоставлением с потоками операционной системы. Вместо этого виртуальные потоки – это концепция, управляемая JVM. Это означает, что нам больше не нужно беспокоиться о них так сильно, как раньше.

Вот базовый пример того, как запустить что-то в виртуальном потоке:

    Thread.startVirtualThread(() -> {
        // Do something in a Virtual Thread
    });

    Thread.builder().virtual().task(() -> {
        // Do something in a Virtual Thread
    }).start();

Если вы думаете, что этот код выглядит ужасно знакомым, вы абсолютно правы. Сохраняя текущее имя и класс, мы можем эффективно сохранить весь наш код и наши инструменты неизменными! В то время как некоторые библиотеки должны будут измениться, чтобы использовать виртуальные потоки, влияние этого изменения крайне ограничено. При использовании Executorservice , который вы должны делать в любом случае , скорее всего , все , что нужно изменить, – это реализация исполнителя!

    // Classic fixed thread pool
    ExecutorService executor = Executors.newFixedThreadPool(10);

    // Threadpool with unlimited virtual threads
    ExecutorService executor = Executors.newUnboundedVirtualThreadExecutor();

Так что вряд ли какие-либо изменения в коде требуются для переключения на виртуальные потоки! Именно такую обратную совместимость мы полюбили (и ожидаем) от нашего любимого языка программирования!

Неограниченное количество (виртуальных) потоков: из

В случае, если вам интересно, вы правильно прочитали предыдущий пример кода: “newUNBOUNDEDVirtualThreadExecutor”. Неограниченный означает “много!”, но как это переводится на потоки ОС? Что ж, повторим: в отличие от текущей реализации Thread , виртуальные потоки больше не являются индивидуальным сопоставлением с потоками операционной системы. JVM выполняет тяжелую работу по обеспечению того, чтобы наши виртуальные потоки в конечном итоге выполнялись в реальных потоках операционной системы.

Итак, если виртуальные потоки – это концепция в JVM … сколько мы можем запускать одновременно? Согласно сообщению “State of Loom” Рона Пресслера (май 2020 года) : Миллионы!

Поскольку создание этих виртуальных потоков обходится дешево, реальной необходимости в объединении больше нет. С помощью Loom мы вступаем в мир, где мы будем создавать (виртуальный) поток для одного действия, а затем просто утилизировать его снова. На самом деле, Неограниченный виртуальный ThreadExecutor выше делает именно это! Всякий раз, когда вы его используете, вы получаете новый блестящий виртуальный поток, который будет уничтожен, как только он выполнит свою задачу.

Блокирующий код больше не является проблемой

В последние годы мы стали свидетелями появления фреймворков, которые утверждают, что обошли ограничения модели параллелизма Java. Эти “неблокирующие” фреймворки добились немалого успеха, и я лично влюбился в Vert.x. Основная идея, лежащая в их основе, часто заключалась в написании кода таким образом, чтобы одновременно блокировалось только ограниченное количество потоков. Это оставляло другие потоки постоянно занятыми. Эти потоки никогда не блокируются, что приводит к повышению общей производительности.

Эти преимущества, как и все в жизни, имели свою цену . Довольно часто эти фреймворки требовали другого стиля программирования, с чем многие программисты (включая меня) боролись. Всякий раз, когда я занимаюсь реактивным программированием, мне кажется, что я больше не программирую Java. Это всегда казалось мне отталкивающим.

С Project Loom нам, возможно, больше не понадобится реактивное, неблокирующее программирование , как оно известно сегодня.

Проще говоря, реактивное программирование – это неблокирующие приложения, которые являются асинхронными и управляемыми событиями и требуют небольшого количества потоков для масштабирования . – docs.spring.io

Поскольку мы можем создавать МИЛЛИОНЫ виртуальных потоков, каждый из которых может быть использован для одного действия, стоимость блокировки виртуального потока близка к нулю! С учетом этих затрат… представьте себе возможности ! Мы можем писать синхронный/блокирующий код без снижения производительности или масштабируемости. Всего несколько лет назад это казалось невозможным, но теперь, с Project Loom, это становится реальностью.

Вывод

Когда Project Look будет завершен и найдет свое постоянное место в JDK, это навсегда изменит наш взгляд на создание высокопроизводительных Java-приложений. Устранение затрат на блокировку потоков при сохранении обратной совместимости – это шедевр инженерной мысли команды проекта.

Я опробовал сборку раннего доступа и был просто сбит с толку тем, насколько интуитивно понятен API. Это мой новый # 1 из удивительных вещей, которые ждут вас в Java!

Короче говоря: “Project Look позволяет Java снова стать той Java, в которую мы влюбились: скучной, но высокопроизводительной <3”.

Дополнение:

Попробуйте сами! Загрузите сборку раннего доступа

Подробнее:

Оригинал: “https://dev.to/tomcools/great-stuff-is-loom-ing-on-the-horizon-for-java-33h0”