Java Guru 🤓
13.4K subscribers
933 photos
15 videos
788 links
Канал с вопросами и задачами с собеседований!

По сотрудничеству и рекламе: @NadikaKir

Канал в перечне РКН: https://vk.cc/cJrSQZ

Мы на бирже: telega.in/channels/javatasks/card?r=lcDuijdm
Download Telegram
Что происходит если не обработать исключение?

Если не было предпринято дополнительных действий, в этой ситуации нет никаких хитростей. Всё приложение, и даже метод main(), выполняется в потоках. Поток, в котором было выброшено и не обработано исключение, остановится, и распечатает стектрейс в вывод System.err. Если это был последний пользовательский поток, приложение начнет завершение работы.

Для изменения логики обработки непойманных исключений в Java существует функциональный интерфейс Thread.UncaughtExceptionHandler.

Обработчик упущенных исключений может быть установлен (в порядке возрастания приоритета):
• глобально на всё приложение, статическим методом Thread.setDefaultUncaughtExceptionHandler();
• для группы потоков, переопределением метода uncaughtException() в реализации объекта подкласса ThreadGroup (т.к. ThreadGroup сам является наследником UncaughtExceptionHandler);
• для отдельного потока, методом setUncaughtExceptionHandler().

Естественно, установка нестандартного обработчика не имеет обратной силы. Используя его, нужно убедиться, что он установлен достаточно рано, до выброса какого-либо исключения.

Хорошей практикой считается обрабатывать исключение настолько близко к месту его выброса, насколько возможно. Следовательно, использование глобальных обработчиков – самый плохой вариант.

Так же как в случае различных финализаций, несмотря на все её недостатки, глобальная обработка иногда лучше, чем ничего. Она может, например, дать последний шанс освободить внешние ресурсы, или уведомить о некорректной работе программы более эффективно, чем через логи.
Когда код с исключением выполняет ExecutorService, мы не имеем прямого доступа к объектам потока. Но в этом случае результатом выполнения будет объект типа Future. Такой отложенный объект при попытке прочитать значение перевыбросит полученное исключение, завернув его в ExecutionException. Новое исключение-обертка уже пойдет по обычному пути обработки текущего потока. Исключение как бы перекочует из внутреннего потока пулла во внешний, который использует этот пулл.

Если же пользовательский код не станет дожидаться результатов, исключение будет потеряно, не оставив даже стектрейса в потоке вывода. Для предотвращения такой ситуации стоит снабдить поток обработчиком сразу после создания, определив для сервиса собственную ThreadFactory.

Обычно, если фреймворк скрывает от пользователя детали работы с потоками, он также скрывает и детали работы с исключениями, оставляя свой специальный способ назначить обработчик. И этот специальный обработчик – более специфичный, а значит более правильный подход, чем стандартная глобальная обработка исключений Java. Так, например, в Spring MVC применяется аннотация
@ExceptionHandler.
👍144🔥3
🧠 Хотите упростить создание тестовой отчетности? 
Ждём вас на открытом практическом уроке «Организовываем отчетность по автотестам на Allure» от OTUS.

💪 На вебинаре разберем:
- интеграцию Allure с Groovy pipeline на Jenkins;
- разницу между TestResult и TestResultContainer;
- интеграцию allure артефактов с Allure TestOps. 

☝️Все это позволит вам оптимизировать работу и сэкономить время на рутинных задачах. 

👉 Зарегистрируйтесь, чтобы посетить бесплатный урок: https://otus.pw/RbCM/?erid=LjN8K9MZw

Встречаемся 15 мая в 20:00 мск в преддверии старта курса «Java QA Engineer. Professional». Все участники вебинара получат специальную цену на обучение и персональную консультацию от менеджеров OTUS! 

Реклама. ООО "ОТУС ОНЛАЙН-ОБРАЗОВАНИЕ". ИНН 9705100963.
👍5🔥1
Из чего состоит пакет java.nio?

Этому вопросу посвящена отдельная страница документации. Если вы никогда раньше не сталкивались с Java NIO – это хорошее место для начала знакомства. Отвечая на этот вопрос, нужно перечислить и объяснить основные понятия NIO:

Буфферы. Временные хранилища фиксированного размера для транспортируемых данных. Именно буферизация – основное отличие неблокирующего чтения от
java.io.

Каналы. Реализации интерфейса Channel – сущности, представляющие соединения между разными участниками ввода-вывода (файлы, сокеты, консоль).

Селекторы. Наследники класса Selector. «Мультиплексоры» каналов – комбинируют несколько каналов в один. Регистрация канала в селекторе возвращает SelectionKey, который содержит ссылку на сам канал, и ряд его атрибутов. Селектор позволяет выбрать из набора зарегистрированных каналов подмножество готовых к работе, при необходимости блокируя выполнение на время ожидания. Каналы и селекторы располагаются в пакете java.nio.channels. Полный пример использования селекторов можно найти в
статье на baeldung.

Кодировки. Charset – то, как бинарные данные будут конвертироваться в родные для Java символы UTF-16 и обратно. Классы для работы с кодировками хранятся в пакете java.nio.charset.
👍10🥰3🔥2
👩‍💻 Как и зачем Java-разработчику сочетать DTO, MapStruct и Spring?

Расскажем на открытом практическом уроке от OTUS.
Спикер занятия — Senior Software Engineer.

На вебинаре мы:

- разберем паттерн DTO (Data Transfer Object);
- обсудим проблемы, которые решает паттерн и его основные сценарии использования на примере небольшого приложения на Spring Boot;
- изучим инструмент MapStruct, чтобы сделать данное сочетание удобным и сократить количество boilerplate кода.

Встречаемся 23 мая в 20:00 мск в преддверии старта курса «Разработчик на Spring Framework».
Все участники вебинара получат специальную цену на обучение и персональную консультацию от менеджеров OTUS!

➡️ Регистрация на урок: https://vk.cc/cwP6FZ

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🥰2
Что такое ForkJoinPool?

ForkJoinPool – специальный вид ExecutorService (пулла потоков), который появился в Java с версии 7. Предназначен для выполнения рекурсивных задач.

Задача для сервиса представляется экземпляром класса ForkJoinTask. В основном используются подклассы RecursiveTask и RecursiveAction, для задач с результатом и без соответственно. Аналогично интерфейсам Callable и Runnable обычного ExecutorService.

Тело рекурсивной операции задается в реализации метода compute() задачи ForkJoinTask. Здесь же создаются новые подзадачи, и запускаются параллельно методом fork(). Чтобы дождаться завершения выполнения задачи, на каждой форкнутой подзадаче вызывается блокирующий метод join(), результат выполнения при необходимости агрегируется.

С точки зрения использования метод ForkJoinTask.join() похож на аналогичный метод класса Thread. Но в случае fork-join поток может на самом деле не заснуть, а переключиться на выполнение другой задачи. Такая стратегия называется work stealing, и позволяет эффективнее использовать ограниченное количество потоков. Это похоже на переиспользование потоков
корутинах Kotlin (green threads).

Примеры практического использования ForkJoinPool.
👍16🔥2😁1
Хотите узнать о технологиях в Яндексе? Слушайте I like techno 🔥

I like techno — подкаст про технологии от Яндекс Еды, Лавки, Такси, Маркета, Доставки и Техплатформы Екома и Райдтеха. В выпусках эксперты рассказывают, что стоит за простыми приложениями в гаджетах, и говорят о бизнесе, продукте и людях, которые создают технологии.

В первых двух эпизодах обсудили технологии в Яндекс Еде и Лавке и продуктовую разработку в Такси и Самокатах.

Узнайте подробнее на сайте подкаста и переходите слушать на YouTube и Яндекс Музыку! 🎧
👍5🔥3🎉2
Чем ForkJoinPool отличается от ExecutorService?

ForkJoinPool сам по себе является наследником ExecutorService. Вопрос подразумевает его отличия от обычного пула потоков – ThreadPoolExecutor.

Преимущества, которые дает work stealing по сравнению с обычным пулом:
• Сокращение расходов на переключение контекста;
• Защита от проблемы голодания потоков (thread starvation);
• Защита от дедлока для рекурсивных задач.

Как положено любому представителю ExecutorService, ForkJoinPool тоже умеет выполнять Runnable и Callable, но помимо этого работает и со специальными задачами ForkJoinTask, о которых также говорилось ранее.

Интерфейс настройки и мониторинга остается тем же, что и в классических тред-пулах.

Каждый обычный пул использует собственный набор потоков. ForkJoinPool по умолчанию использует общий пул-синглтон commonPool. Альтернативный отдельный пул всё еще можно задать в конструкторе.

ForkJoinPool сам регулирует количество запущенных потоков, достигая максимальной эффективности при заданном уровне параллелизма.
👍13🔥3😁2
📘 С чего начать изучение Apache Kafka?

Apache Kafka — многогранный и непростой инструмент. Даже если вы уверены, что знаете его, наш курс докажет вам обратное!

💻 Начните работу с Kafka на открытом практическом уроке от OTUS, где вы:

— разберете особенности и устройство Kafka;
— познакомитесь с основными утилитами;
— рассмотрите базовое API для работы с Kafka.

Спикер — опытный разработчик и преподаватель.

Встречаемся 20 мая в 20:00 мск в преддверии старта курса «Apache Kafka». Все участники вебинара получат специальную цену на обучение и персональную консультацию от менеджеров OTUS!

👉 Регистрируйтесь прямо сейчас, чтобы не пропустить бесплатный урок: https://vk.cc/cwQEYN

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
👍3🔥2
Как работают параллельные стримы?

Основная цель, ради которой в Java 8 был добавлен Stream API – удобство многопоточной обработки.

Обычный стрим будет выполняться параллельно после вызова промежуточной операции parallel(). Некоторые стримы создаются уже многопоточными, например результат вызова Collection#parallelStream(). Для распараллеливания используется единый общий ForkJoinPool.

Внутри реализации потока его сплиттератор оборачивается в AbstractTask, который и отправляется на выполнение в пул. AbstractTask при выполнении считывает estimateSize сплиттератора и текущую степень параллелизма пула. На основе этих данных он принимает решение, распараллелить ли сплиттератор на два методом trySplit().

У удобства такого решения есть обратная сторона. Так как пул единый, нагрузка распределяется на всех пользователей параллельных стримов в программе. Если в одном потоке выполняются долгие блокирующие операции, это может ударить по производительности в совершенно не связанном с ним другом потоке.

Если всё же требуется использовать отдельный пул потоков, сам стрим выполняется как задача этого отдельного пула.
👍53🔥2
Москва, приглашаем 25 мая на One Day Offer для Java-разработчиков 😉

Сбер ищет опытных Java-разработчиков для создания нового продукта класса ERP для учёта и планирования хозяйственной деятельности, расчёта заработной платы. Проект полного цикла от подготовки требований до внедрения и сопровождения.

Всего за один день вы сможете пройти все этапы отбора, познакомиться с будущей командой и получить оффер.

В работе мы используем:

✔️ Java 17, Spring Framework
✔️ Микросервисную архитектуру
✔️ Service Mesh, Kafka
✔️ WildFly, PostgreSQL, приложения с открытым исходным кодом
✔️ Сервисы Jenkins, Ansible, Git/BitBucket, Nexus, Jira, Confluence

Что будем делать?

✔️ Участвовать в полном цикле разработки компонентов и сервисов с нуля.
✔️ Проектировать и разрабатывать backend, API.
✔️ Внедрять масштабный продукт класса ERP для учёта и планирования хозяйственной деятельности.
✔️ Разрабатывать коммерческую версию ИТ-продуктов.
✔️ Оптимизировать производительность продуктов и сервисов.

Приглашаем в команду Java-разработчика для создания нового конкурентного продукта на современном технологическом стеке Platform V!

Регистрируйтесь по ссылке 👈
🎉8👍5🔥2
Чем CompletableFuture отличается от Future?

Future – интерфейс, который представляет пока еще недовычисленный результат. Когда породившая его асинхронная операция заканчивается, он заполняется значением. Метод get блокирует выполнение до получения результата, isDone проверяет его наличие. К примеру результат выполнения задач в ExecutorService, ForkJoinTask, реализует интерфейс Future.

CompletableFuture появился в Java 8. Это класс-реализация старого интерфейса Future, а значит всё сказанное выше справедливо и для него. Вдобавок к этому, CompletableFuture реализует работу с отложенными результатами посредством коллбэков. Метод thenApply регистрирует код обработки значения, который будет автоматически вызван позже, когда это значение появится.

В Java 9 прогресс пошел дальше, и появилась библиотека Flow API. Это встроенная реализация реактивных стримов. Реактивный стрим, сильно упрощая, – это более общий случай, последовательность отложенных значений. Другая их реализация – популярная, но не входящая в стандарт библиотека
Reactive Extensions (RxJava).
👍10🔥21😁1
Стать бэкендером в Яндексе за выходные

8–9 июня устраиваем Weekend Offer Backend: всего за 2 дня можно пройти технические секции и попасть в Яндекс. Для этого нужно зарегистрироваться и решить несколько задач в Контесте.

Вы сможете выбрать одну из команд: Crowd, Ecom-сценарии, Поиск, Алиса, Автономные автомобили и Большие данные. Можно пообщаться с нанимающими менеджерами и выбрать самый интересный проект. Если всё пройдёт хорошо, сразу же получите офер.

Нанимаем в офисы России и Республики Беларусь.

Узнать подробности и зарегистрироваться можно здесь.
👍5🔥31
Зачем выбирать ReentrantLock вместо synchronized?

Объект класса ReentrantLock решает те же задачи, что и блок synchronized. Поток висит на вызове метода lock() в ожидании своей очереди занять этот объект. Владеть локом, как и находиться внутри блока synchronized может только один поток одновременно. unlock(), подобно выходу из блока синхронизации, освобождает объект-монитор для других потоков.

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

Шире и возможные режимы блокировки. Кроме обычного ожидающего lock(), вариант tryLock() с параметром ожидает своей очереди только заданное время, а без параметра – вообще не ждет, а только захватывает свободный лок.

Еще одно отличие – свойство fair. Лок с этим свойством обеспечивает «справедливость» очереди: пришедший раньше поток захватывает объект раньше. Блок synchronized не дает никаких гарантий порядка.
👍17🔥2
👩‍💻 Java Библиотека - топовое сообщество Senior Java Developer, где он делится советами, статьями и лайфхаками чтобы вы стали топовым разработчиком!

👩‍💻 Android Developer - канал для андроид разработчиков! Статьи, вопросы и задачи с собеседований, лайфхаки.

👩‍💻 Kotlin Developer - самый топовый канал для котлин разработчика!

📕 Книги для Java программиста - канал с книгами по Java. Постоянно выходят новинки как на русском так и на английском языке!

📰 Java News - канал с последними новостями из мира Java!
Please open Telegram to view this post
VIEW IN TELEGRAM
Как используется метод Lock.newCondition()?

Если реализации интерфейса Lock представляют высокоуровневую альтернативу блока synchronized, то реализации его спутника, интерфейса Condition – альтернатива методам notify/wait. Оба этих интерфейса относятся к пакету java.util.concurrent.locks.

Как и ожидание на мониторе, Condition реализует примитив синхронизации «Условная переменная». Один или несколько потоков зависают на объекте-кондишне с помощью варианта метода await (ждут удовлетворения условия). Другой поток пробуждает их методами signal и signalAll (сигнализирует об удовлетворении условия).

Конкретные реализации Condition всегда решают те же задачи, что блокировка на мониторе, но в теории могут отличаться в нюансах поведения. Например, может не быть требования вызывать ожидание/сигнал только при захваченном локе (аналог требования, по которому notify/wait всегда вызываются в synchronized). Или может гарантироваться порядок получения сигнала ожидающими потоками.

Возвращаясь к поставленному вопросу, Condition всегда связан со своим объектом типа Lock, и метод Lock.newCondition() – единственный правильный способ создания кондишна.
👍61
This media is not supported in your browser
VIEW IN TELEGRAM
Cамый простой способ изучить Java — залезть в голову профи

Один из лучших айтишников России учит базе кодинга в Telegram. Даже гуманитарий поймёт, как создавать приложения, сайты, игры и чат-боты.

Достаточно подписаться на «Секреты Java», где каждый день появляются гайды, готовые примеры кода и лучших практик.

И всё это бесплатно — вместо сотен тысяч рублей за курсы. Стартовать в прибыльной профессии с нуля вы сможете гораздо проще!

Теперь обучиться Java может каждый: @java_secrets
😐2🎉1🥱1
Чем отличается ReentrantLock от обычного Lock?

Lock – это интерфейс, ReentrantLock – его реализация. «Reentrant» говорит о том, что один и тот же поток может перезахватывать уже захваченный лок. Интерфейс не требует этого свойства. Обычный блок synchronized тоже является reentrant – вложенная синхронизация на том же мониторе отработает без проблем.

Примеры не-reentrant локов из стандартной библиотеки – представления класса StampedLock, возвращаемые его методами asReadLock() и asWriteLock().
2👍1
💻 Готовы ли вы изучить Apache Kafka на профессиональном уровне и работать с данными еще эффективнее?

Пройдите короткий тест и узнайте!

⚡️ В случае успешного прохождения вас ждут подарки — доступ к открытым урокам для знакомства с форматом обучения и специальная цена на курс.

Всего за 3 месяца вы освоите Kafka, базовые API, фреймворки Kafka Streams, Spring, Akka и ZIO, ksqlDB, Schema Registry и многое другое!

🌐 Проверьте, готовы ли вы к расширению карьерных возможностей: https://vk.cc/cwXChB

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
👍2🔥1👏1
Как использовать ReadWriteLock?

Стандартный интерфейс ReadWriteLock предоставляет потокобезопасный разделенный доступ на чтение и на запись. Для этих целей в нём объявлены два метода: readLock() и writeLock(). Они возвращают объекты под интерфейсом Lock.

Оба типа блокировок одного экземпляра ReadWriteLock связаны. Пока какой-то поток не заберет блокировку на запись, сколько угодно потоков могут читать не мешая друг другу. Блокировкой readLock закрывается часть кода с семантикой «только чтения» некоторого условного «ресурса». В критической секции кода writeLock осуществляется модификация ресурса.

Свойства этих локов защищают программу от ситуаций конкурентной записи ресурса и чтения во время записи. Подобно copy-on-write коллекциям, этот подход становится выгодным, когда ресурс читают сильно чаще чем модифицируют.

Интерфейс реализуется классом ReentrantReadWriteLock, который во многом похож на обычный ReentrantLock.
👍11🔥3🎉3
Присоединяйтесь к нашему бесплатному курсу и начните увлекательное путешествие в мир Java!

Изучайте основы, создавайте программы, разбирайтесь с методами и анализируйте ошибки в коде. Практика, упражнения и проверочные тесты помогут вам освоить навыки программирования.

🎓 Чему вы научитесь:
— Создавать программы с использованием основных конструкций языка.
 — Разделять код на методы для повторного использования.
 — Анализировать ошибки в коде с использованием отладочной печати.

💼 Включено в курс:
29 уроков (видео и/или текст), 35 упражнений в тренажере, 95 проверочных тестов + дополнительные материалы.

Вы с нами?😉
👍7