Project Loom. Асинхронная многопоточность в Java 15
Vložit
- čas přidán 26. 03. 2020
- Project Loom: эффективная асинхронная многопоточность в Java 15. Реализация идеи Fibers (файберов) и Continuations (континуаций) - легковесных потоков в Java.
Поддержать проект:
➡ Стать спонсором czcams.com/users/letscodedrujoin
➡ Patreon / letscodedru
➡ Яндекс.Деньги money.yandex.ru/to/4100145167...
➡ PayPal paypal.me/letscodedru
➡ Qiwi qiwi.me/letscode
Текущая реализация многопоточности в Java на момент выхода JDK 14 строится вокруг Threads - потоков (тредов) операционной системы. Данный подход не плох сам по себе, но имеет ряд существенных проблем при высокой нагрузке: во-первых экземпляр потока занимает достаточно много оперативной памяти, во-вторых, при большом количестве потоков процессор тратит много времени на переключение между ними, в третьих, при работе с медленными ресурсами (диск, сеть, БД), потоки могут блокироваться и впустую тратить время процессора (во время блокировки потока, процессор ничего не делает).
Для решения этой проблемы в Java вводятся различные сущности и абстракции. Самые яркие из них - ForkJoinPool и CompletableFuture, которые позволяют запускать задачи на выполнение в асинхронной манере без порождения лишних потоков на уровне операционной системы.
Следующий важный шаг - введение Fibers (файберы), Continuations (континуации) и yield (вытеснение). Эти сущности позволяют создавать легковесные потоки сотнями тысяч, без больших затрат оперативной памяти и процессорного времени на переключение контекста потоков на уровне ОС. В любой момент времени задача может вытеснить себя во время выполнения и освободить рабочий тред для другой задачи, повышая утилизацию процессора.
GitHub проекта Loom:
github.com/openjdk/loom
Официальная страница проекта Loom на сайте java.net:
jdk.java.net/loom/
Мейллисты проекта Loom за март 2020:
mail.openjdk.java.net/pipermai...
Статья на хабре, с хорошим описанием того, как происходит вытеснение континуаций в файберах:
habr.com/ru/company/jugru/blo...
Черновики (весьма скудные) документации по проекту:
wiki.openjdk.java.net/display...
wiki.openjdk.java.net/display...
wiki.openjdk.java.net/display...
➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖
➡ Второй канал: / geekchatdru
➡ Twitch: / drucoder
➡ Твиттер: / letscodedru
➡ Группа Вконтакте: letscodedru
➡ Канал в Telegram: t.me/letsCode_dru
➡ Чат в Telegram: t.me/joinchat/FeiP9xEhqHajfqh...
➡ Сервер в Discord: / discord
➡ Яндекс.Дзен: zen.yandex.ru/media/id/5ac209...
Очень хотелось бы узнать подробнее про ForkJoinPool
Рили,я его юзал,но под капотом глубоко не вникал
+1. Еще с прошлого стрима хочу послушать про ForkJoinPool
czcams.com/video/t0dGLFtRR9c/video.html - вот тут очень хорошо про ForkJoinPool
Алексей Шипилев, его доклад смотрите
Сделай про форк джоин пул, раз уж пошла такая тема.
czcams.com/video/t0dGLFtRR9c/video.html
Опытный разработчик всегда посмотрит направо и налево, даже если переходит улицу с односторонним движением.))
Жги дальше, дружище XD
Как же я этого ждал
Недавно попал на канал и сразу подписался. В джаве не новичок, но то о чем тут рассказывают, и главное как, заставляет отложить все и вникать))
Методика очень необычная (по моему опыту), и очень действенная. Максимально приближенно к практике - это очено ценно.
Я на плейлисте sweater целую курсовую нафигачил - получилось отлично
@@user-uq4nd6go9c я на свитере диплом нафигачил и защитился на отлично))
@@user-uq4nd6go9c я с помощью свитера на работу вторую устроился
Большое спасибо за видео.
Спасибо огромное!
Почему ещё не было видео про ForkJoinPool? (Ирония)
Спасибо, как всегда пушка!!
Спасибо за видео. Есть несколько замечаний:
0:10 - немного преждевременный оптимизм по поводу выхода preview-версии JDK 15. Откуда взялась эта информация? Про это никто точно не писал ни в Wiki, ни в рассылке. То, что сборки Loom сейчас базируются на JDK 15, ничего не означает. И уж точно в JDK 17 не будет стабильной версии.
6:18 - всё-таки это не JDK 15, а Loom Early-Access Build, основанный на JDK 15.
6:40 - в IDEA есть комбинация кнопок Ctrl+Shift+Enter, которая автоматически вставит фигурные скобки и поставит курсор сразу на новую строку.
15:50 - не объяснено, что такое Executors.newUnboundedExecutor(). Это новый метод, который выполняет каждую задачу в новом потоке.
23:24 - нет, всё не происходит в одном потоке. Это разные потоки, просто у них одинаковые имена:) (из-за того, что вы явно прописали name в билдере).
И есть ещё общее замечание по поводу содержания. Очень важная фишка Loom - это возможность вызывать блокирующие network операции из виртуальных потоков, и эти операции не будет пинить реальные потоки и просаживать ресурсы. Для полноты можно было бы привести небольшой пример с каким-нибудь Socket.accept().
Конструктивно. По делу. Спасибо)
22:22 Ух бля. Я уже предвкушаю баги от потерянного секьюрити контекста, например Спринга, из-за того, что исполнение началось в одном потом потоке, а закончилось в другом.
Миллениалы нашли файберы)) Годно.
*Кто исполняется не в виртуальных машинах - улыбнулись, я улыбался.
Я аж подписался. И колокольчик нажал.
Хотелось бы посмотреть в похожем ключе про Valhalla.
Давно пора было запилить корутины из Котлин на Джаву. Рад, что эта фитча уже в разработке.
Андрей, нравится ваша манера "думать" на языке программирования) вы реально общаетесь с машиной. по крайней мере возникает такое впечатление при посмотре))
вотэтаповорот)))
Норм.
Корутины подвезли))
9:45 + :D
ForkJoinPoo интерен
О нет, о нет, джаву поразил вирус ноды))
Continuations это как генераторы в ноде
По ходу в 15 джаву Loom не попал.
Поэтому - интересует отдельное видео про ForkJoinPool :)
Ого, джава возможно скоро сможет как Node.js
just ty
все здорово и классно, у меня вопрос: сможешь показать пример многопоточности или ансихронyости в Javafx?
проснулся ототого что посоветовали лечь спокойно
"Teach me"(c)
в душе не представляю, как пользоваться [вот то что ты сказал]
Видимо речь про ForkJoinPool
Речь о том, что внятной документации ещё нет. Пока не ясно, как это правильно готовить, поэтому я в душе не представляю, что они закладывают как правильное использование. То, что я вам показал - это основано на тестах из исходников, примеров из Мейл рассылки и моих локальных тестов этой технологии
Эта фича предназначена для решения проблем, которые уже решают netty, asynchttpclient и прочие. Это стандартизированная реализация асинхронности с которой должны поиметь буст в производительности и отсутствие костылей которыми набита та же netty.
Что по поводу CompletableFuture?
А можно видео о ForkJoinPool ?
А как там с thread local и виртуальными потоками? Например при логировании с MDC
Все с ними нормально будет в итоге. Никто про них не забыл)
По-моему, такой подход "ломает" ThreadLocal переменные. В спринге и не только на них, например, завязана транзакционность. Если перескочить не подумав то многие штуки сломаются. Или в loom'е есть совместимость по ThreadLocal?
Это отдельная головная боль разработчиков. И они обещают ее решить
Нововведение выглядит как попытка покушения на эрланг =)
Из видео не понял вытесняется ли заблокированная на thread.sleep задача...
Да, вытесняется. Как это работает ещё разберу ближе к релизу, когда больше определенности будет
сделай обзор котлин 1.4 еа
А чем это решение отличается от реактивного прогриммирования введеного в 9-ой версии? Там вроде так же, создаем ForkJoinPool с нужным количеством потоков (каждый поток/подписчик) работает ассинхронно, процессорные ресурсы размазываются равномерно и неполучится так что кто-то перегружет а кто-то ждет. К сожалению много в чем там еще не заробрался (с обратной связью request, на случай если подписчик непоспевает за источником а стек начинает переполнятся и лишние "публикации" пропадать).
Короче, если бы вам захотелось раскрыть эту тему то думаю что многим бы понравилось,
А так спасибо вам за интересный канал, где показана именно практика а не длинные нудные теории и где напирается ручками и с ошибками а не просто копипаст.
думаю разница в смене контекстов.
Разница в том, что в forkjoin ты не можешь сказать сделать условие прям внутри задачи "если в буффере меньше 1мб данных, то вытеснить задачу", освободив воркера, а потом стартануть конкретно задачу снаружи этого кода. При этом не вызывая блокировки физического треда ос. Разница в подкопотной возне
@@user-oj5gu2kb1k На Rx'е можно все написать на ForkJoinPool'е или его аналоге такого же размера, ну смысл в том чтобы потоков было столько же, сколько и ядер (+-1), тогда вытеснений и смены контекстов не будет. А если еще и NIO везде правильно затулить, то смен контекста не будет и вовсе (только синхронизации). Но так не принято.. ))) Либа не дает новых возможностей, это просто новый подход, который только возможно немного упростит решение некоторых специфических задач.
тем, что старый блокирующий код практически без доработок превратится магическим образом в асинхронный?
никаких больше колбеков и completablefuture
пишите на блокировках обычный серверный код и он будет также эффективен и расширяем, как если все покрыть completablefuture, rx и асинхронными драйверами
такое уже сделано давно в golang -- теперь будет и в java
весь асинхронный код из современного и модного превращается в легаси, а весь блокирующий легаси код становится современным и модным
Кажется, это было бы бессмысленно без того, чтобы переписать все блокирующие IO вызовы на асинхронные -- но в том то и дело, что они их переписали)
@@andrei_bo Андрей, магии не бывает. Была бы магия, не было бы NIO и NIO2. Java - очень четко детерминированная машина с четким определением потоков и Memory Model. Синхронная архитектура сама по себе (или магическим образом) асинхронной не станет, может поломаться обратная совместимость.
Как происходит фиксация состония при вытеснении? Что будет с внушительным набором утилит, заточенных на работу с абстракциями потоков (семафоры, барьеры и тп)?
Про состояние читай статью на Хабре (ссыль в описании). Утилиты - тут сложно. Как обычно, надо будет переписать их)
А в чём разница между loom и rxjava?
Rx java не связана с многопоточной обработкой напрямую. Это вообще про реактивность (не делать лишней работы и делать ее вовремя, асинхронно). А тут - не допускать простоя процессора, когда есть другая работа
Простите за вопрос, сами мы не местные... async/await когда-нибудь будет? .NET, Python, JS, Rust, C++ - везде есть
Не хотят его вводить пока что. Есть у этого подхода свои минусы: смешивать синхронный и асинхронный режимы иногда неприятно (в пайтоне так вообще больно). Поэтому хотят попробовать сделать это сделать максимально бесшовно, чтобы в большинстве случаев кодер даже и не задумывался, какой у него тут подход
@@letsCodeDru Жаль, конечно, хотелось бы уже увидеть... Будем надеяться.
Проблемы в Python, я думаю, связаны с проблемами с многопоточностью (GIL), в других языках проблем с async/await вроде должно быть меньше.
Вообще, собственно философия async/await в том и заключается: писать фактически асинхронный код, но так, чтобы он выглядел как синхронный. Об отличии напоминают только эти слова - async и await. В общем, относительно безболезненно для кодера, казалось бы. Но опыт .NET показал, что переход на стиль async/await, действительно, имеет свои проблемы...
Хотя проблемы есть только при переводе старого кода на новый стиль, а в новом коде всё ОК.
а зачем они нужны?) тут бесшовно сделают весь синхронный и блокирующий код асинхронным как в go. другими словами, не надо писать async/await, а оно будет работать, как будто они везде есть)
то есть легковесный потоки -- полная альтернатива async/await
Вышла 17-я Java LTS. Но проекта Loom в ней нет :-(
За обзор - спасибо! Thread'ы конечно тяжелые, но не особо. В реальности это действительно имеет смысл наверно когда у вас > 1000-5000 потоков в приложении или работа на слабом железе (Типа Raspberry Pi 1). Получается, что они добавили внутреннее переключение потоков при паркове потока (sleep, Unsafe.park, synchronize). И я так понимаю, что есть некоторое ограничение, что если у вас допустим 4 потока в форкДжоине, и вы засабмитите 4 while(true){} задачи, что все зависнет и 5ая задача уже сядет в очередь, потому что виртуальные потоки не умеют вытесняться. Так как в вайл-тру нету парковки, а смена контекста происходит только при парковке. Интересно, как виртуальные потоки будут реагировать на блокирующие IO?! Я так понимаю мне просто нужно пойти на хабра (или..) и прочитать статью :) А вообще переодически сталкиваюсь с подобной задачей, она очень специфична и для этих целей у меня есть свой самодельный менеджер потоков)
Вроде как они пытаются вычислять блокирующие вызовы и делать автоматическое вытеснение. Если в виртуальном треде вызвать Thread.sleep, то вытеснение произойдет. Следовательно, тут они отлавливают эту проблему, а значит и в других подобных местах смогут выловить
@@letsCodeDru Да, sleep, Unsafe.park, synchronize - обернули и тут они могут сделать вытеснение, тем более зная, что поток сейчас пока может отдохнуть, пулу можно дать другую задачу. Допустим штатное блокирующие IO тоже обернут (хотя может и запретят вызывать, потому что, по-сути поток простаивает, но или будут переводить в IO-пулл), JNI должны запретить вызывать с виртуальных потоков. Но в "while(true){}" вклиниться сложно, потому что это сожрет производительность. Насколько я знаю, такие вещи в джаве делаются инструментацией кода на уровне JVM, а проще говоря - после каждой команды нужно if-чик вставить. Не уверен, что они смогут прерывать стек да и чем это будет отличаться от OS-ных потоков?! В этом и смысл легковесных потоков, что не нужно тратить время на прерывание стека и вытеснение, поток сам должен отдать управление, дойдя до контрольной точки, тогда программа будет наиболее производительна и оптимизирована.
5000 потоков это уже дохрена
@@ZhekaKozlov 1 ядро без проблем разруливает под 1000 потоков. 8 ядер - соответственно.. А 16-32 ядра.. Я сколько делал опыты на сравнение IO и NIO - разницы почти нету. В 2008-2012 это имело смысл. Байки про зеленые потоки и возможность хендлить 5-10-100К коннекшенов одновременно, остались актуальны ДО эпохи современных клаудов. Blocking-IO и ExecutorService остается самым известным и простым способом для ежедневных проблем. Все высоконагруженные задачи в энтерпрайзе давно решают клаудами, не качеством, а количеством. Как бы ты не оптимизировал код, возможности его масштабируемости иссякнут довольно скоро, а у клауда - главное чтобы маштабировалось.. На самом деле, я считаю, что в этом всём мало смысла, этот инструмент уменьшает порог вхождения, актуален для маленького спектра задач. Такие парадигмы либо сразу, либо никогда.
@@jad7kii когда можно сэкономить от 100k$ в месяц на железе подобные оптимизации мастхэв. Обычный г*вноэнерпрайз нормально на замшелом спринге пишется, поднимается сотня-другая контейнеров и всё работает. Но есть проекты на которых готовы платить за гораздо более высокий throughput при использовании минимальных мощностей. "Стандартный" стек для этого просто не подходит. Участвовал в разработке одного банковского решения которое после переписывания со "стандартного" стека и оптимизаций получило 100 кратный буст по throughput, потребляемой памяти и утилизации. Короче говоря - каждому проекту свой инструмент.
А fibers будут?
На текущий момент есть ощущение, что файберы - это концепция, а не сущность, которая складывается из виртуальных тредов и континуаций с вытеснением.
@@letsCodeDru Fiber это старое рабочее название VirtualThread. В общем, это одно и то же.
Думаешь волокна таки выкатят в 17-ой? Было бы хорошо.
В Java будет новая фича, ответ Kotlin и Go на их корутины/горутины.
Если все получится, то Рон Пресслер будет просто красавчик.
Go на данный момент разносит джаву при сильных нагрузках в прах. До 10 раз быстрей ответ ответ при нагрузке.
Правда долбит проц и память в сотку
@@user-oj5gu2kb1k Ядро Java закладывалось в совершенно других технологических обстоятельствах. С того времени подходы и технологии сильно изменились. С волокнами хотят исправить ситуацию. Сейчас частые релизы версий на то и нацелены, что бы актуализировать Java под современные подходы. И это получается.
Java сливает из-за блокировок и переключений контекста. Fibers как раз и созданы, чтобы исполнение было неблокирующим и максимально лёгким. По идее, мы должны получить ситуацию как с го: максимальная утилизация процессора и лютейшие скорости
@@letsCodeDru Все же реально думаю это будет новая килл-фича джавы. При прочих равных в разработку будут выбирать Java. Конечно оперативку JVM всеровно кушает очень прилично, тут у нее не отнять. Но в замен огромный багажник наработок, подходов и фреймворков. Так что для корп сегмента особо без вариантов. Я кстати пробовал Go... Хз, мне не зашло... Я бы не сказала, что синтаксис там прям понятный, не явная реализация интерфейсов, структуры программ и подходы какие-то не устаявшиеся, каждый лепит как может... Вообще принцип наименьшего удивления нарушается там сплошь и рядом...
Я не хочу сказать что язык плохой, но после Java, с ее структуированостью, строгостью, ООП Go совсем не ложиться на душу.
Еще не посмотрел до конца, это потоки типа горутин в Go?
Ага, типа того. Легковесные потоки
типа go-рутин и ko-рутин
И дохрена чего ещё)
@@letsCodeDru поделись что за ОСЬ у тебя стоит:)
@@letsCodeDru на самом деле, смысл остается тем же. Реализация другая. Очень жаль, что к этому подходу оракл шел очень долго.
Аля картины)?
Кто в современном мире запускает Java сервисы на Windows Server?) А?)))
Project javaSoset
Да это ж корутины или файберы стандартные, джава сильно отстала в етом плане, даже в Lua давно есть
ты слово корутины слышал?
Фича выглядит юзабельно. Но мне кажется мало смысла в обозревании фич находящихся на настолько раннем этапе разработки. По крайней мере детальный разбор смысла не имеет, рассказ в общих чертах - ок. Просто к релизу фичи может оказаться, что весь код из видео бесполезен и работает всё совсем не так, как ты рассказываешь.
Да, полностью согласен) но мне, как гику, это люто все интересно и хочется поделиться с другими гиками этой крутотенью) тем более, раньше начнем приглядываться - проще будет понять концепцию, раньше возьмём в работу)
@@letsCodeDru я тоже гик(что бы это не значило..), расскажи поподробнее про многопоточность! плиз) и если можно подетальнее, для начинающих гиков)))
В своих выступлениях да и в публикациях Пресслер дал понять, что общая концепция не изменится, может поменяться реализация в коде и тд, но в целом я так понял подход утвержденный и вполне жизнеспособный. На видео автор так и сказал, что кодовая реализация постоянно меняется. Основная ценность видео в концепции.
Очень хотелось бы узнать подробнее про ForkJoinPool