Топ-3 статьи о Java и смежных технологиях за неделю по версии нашего канала.
Подробный разбор Apache Kafka — от базовых концепций до внутреннего устройства. Топики, партиции, репликация, consumer groups и принципы хранения сообщений.
Думаю, отличная статья для тех, кто хочет понять, почему Kafka стала стандартом де-факто в микросервисной архитектуре.
Production-кейс о deadlock при работе с CompletableFuture и ThreadPoolTaskExecutor.
Проблема: родительская задача блокирует единственный поток через join(), ожидая дочерние задачи, которые не могут стартовать.
Глубокое погружение в три типа совместимости: source-level, binary и behavioral. Разбор на примерах: почему добавление перегруженного метода сохраняет binary compatibility, но может нарушить поведение.
Обязательно к изучению перед рефакторингом публичных API.
#News
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥2❤1👾1
Наш подписчик спрашивает:
У меня на проекте сейчас миграция legacy на Spring Boot 3.2 с Java 21. Обсуждаем с командой включить виртуальные треды. В интернете встречаю противоречивые мнения. Одни показывают бенчмарки с 5-кратным улучшением производительности, другие пишут, что в реальных проектах не заметили разницы или даже словили деградацию перформанса.
Система у нас типичная: REST API → БД → внешние сервисы. Как думаете, стоит ли игра свеч?
🔹 Что думаете?
— Кто реально использует виртуальные треды в проде? Какие результаты?
— В каких сценариях они действительно дают профит, а где бесполезны?
— Есть ли подводные камни, о которых не пишут в гайдах?
P.S. Если хотите задать вопрос, заполните нашу гугл-форму. Это займет 5 минут.
#DevLife
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥2😁1
Forwarded from Библиотека собеса по Java | вопросы с собеседований
Напишите метод для production-кода 👇
📦 Задание
Реализуйте метод, который выполняет операцию с повторными попытками:
public <T> T retry(Supplier<T> operation,
int maxAttempts,
long initialDelayMs) {
// Ваш код здесь
// При неудаче - повторить с задержкой
// Задержка удваивается: 100ms -> 200ms -> 400ms
// После maxAttempts выбросить исключение
}
Требования
— Первая попытка без задержки
— Каждая следующая: задержка *= 2
— После maxAttempts пробросить последнее исключение
— Если успех - вернуть результат
Ставьте → 🔥, если нравится формат. Если нет → 🤔
#practise
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13❤11👍3🤔1
Очередная неделя позади, надеюсь ваши пайплайны в порядке и на выходных есть время на отдых.
Делитесь фотографиями, как проходят выходные: учёба/пет-проекты/поездки/встречи.
Я сегодня поделюсь видом на Которскую бухту сверху 😍
Отправляйте фото в комментарии👇🏻
#DevLife
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
😍5👍4🔥4❤1
Когда проектируешь систему с email-уведомлениями, важно понимать не только Spring Boot Starter Mail, но и что происходит уровнем ниже.
SMTP — это то, на чём всё держится. И если знать его команды и коды ответов, можно быстрее находить проблемы: почему письмо ушло в спам, где потерялось, какой сервер отклонил.
Про сам протокол можно почитать подробнее тут.
А так это выглядит на пратике👇🏻
Properties props = new Properties();
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.port", "587");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
Session session = Session.getInstance(props, new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress("[email protected]"));
message.setRecipients(Message.RecipientType.TO,
InternetAddress.parse("[email protected]"));
message.setSubject("Тема письма");
message.setText("Текст сообщения");
Transport.send(message); // Здесь и запускается SMTP-танец
@Service
public class EmailService {
@Autowired
private JavaMailSender mailSender;
public void sendEmail(String to, String subject, String text) {
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(to);
message.setSubject(subject);
message.setText(text);
mailSender.send(message);
}
}
Зависимость:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
ИЛИ
implementation 'org.springframework.boot:spring-boot-starter-mail'
application.yml:
spring:
mail:
host: smtp.gmail.com
port: 587
username: [email protected]
password: your-app-password
properties:
mail:
smtp:
auth: true
starttls:
enable: true
🔹 starttls.enable — шифрование соединения (команда STARTTLS в SMTP)
🔹 mail.smtp.auth — аутентификация на сервере
🔹 Порты: 25 (обычный), 587 (TLS), 465 (SSL)
Когда понимаешь, что происходит на уровне протокола, легче дебажить: смотришь логи Transport, видишь SMTP-коды ответов (250 OK, 550 rejected и т.д.) и сразу понятно, где проблема.
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤2🔥1
Ctrl + Shift + F7 → Подсветка всех использований в файле
🔹 Когда это спасает
— Рефакторите метод и хотите быстро увидеть все места вызова? Один клик — и все использования подсвечены жёлтым.
— Не нужно открывать Find Usages и искать глазами.
— Ставите курсор на переменную → хоткей → мгновенно видите весь её жизненный цикл в файле.
— F3 и Shift + F3 для быстрого прыжка между подсвеченными местами.
— Esc убирает подсветку.
🔹 Почему это удобнее Alt + F7
— Не открывается отдельная панель.
— Работает молниеносно даже на огромных проектах.
— Идеально для локального анализа: видите использования только в текущем файле, без шума из других классов.
🔹 Бонус
— Работает для переменных, методов, классов, полей.
— Комбинируйте с Ctrl + W (расширить выделение), чтобы быстро выделить нужный участок кода.
#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍6❤2
🧠 Готовишься к собесам, а ноутбук еле тянет IDE?
Самое время прокачать скиллы и апгрейднуть железо!
Proglib Academy разыгрывает MacBook Pro 14 (M3 Pro, 36 GB, 1 TB SSD) 💻
Купи любой наш курс до 15 ноября → пройди 2 недели обучения → напиши куратору #розыгрыш. Всё, ты в игре!
📚 Среди курсов:
▫️ Алгоритмы и структуры данных — топ для подготовки к собесам в Яндекс и FAANG.
▫️ Архитектуры и шаблоны проектирования — чтобы думать как senior.
▫️ Python, математика для DS, основы IT и другие направления.
👉 Принять участие
Самое время прокачать скиллы и апгрейднуть железо!
Proglib Academy разыгрывает MacBook Pro 14 (M3 Pro, 36 GB, 1 TB SSD) 💻
Купи любой наш курс до 15 ноября → пройди 2 недели обучения → напиши куратору #розыгрыш. Всё, ты в игре!
📚 Среди курсов:
▫️ Алгоритмы и структуры данных — топ для подготовки к собесам в Яндекс и FAANG.
▫️ Архитектуры и шаблоны проектирования — чтобы думать как senior.
▫️ Python, математика для DS, основы IT и другие направления.
👉 Принять участие
❤1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁32💯2🔥1
Forwarded from Библиотека задач по Java | тесты, код, задания
Что будет при обращении к api/products без параметров?
Anonymous Quiz
50%
page будет равен 0
6%
page будет равен null
28%
код не скомпилируется
9%
вернётся ошибка 415
6%
Посмотреть ответ
😁8👍4❤2🔥2
ConcurrentSkipListMap — это потокобезопасная реализация NavigableMap из пакета java.util.concurrent.
В отличие от ConcurrentHashMap, эта структура поддерживает упорядоченность элементов и основана на вероятностной структуре данных Skip List (список с пропусками).
📦 Базовая структура
Внутри ConcurrentSkipListMap использует многоуровневый связанный список Skip List (см. фото).
Главная особенность:
— Элементы отсортированы по ключу (естественный порядок или Comparator).
— Несколько уровней индексации для быстрого поиска.
— Lock-free операции чтения через CAS (Compare-And-Swap).
— Минимальные блокировки только при изменении структуры.
🔍 Как устроено хранение
Базовые компоненты:
▪️ Node<K,V> — узел нижнего уровня.
▪️ Index<K,V> — узел индексного уровня.
▪️ HeadIndex<K,V> — голова уровня, хранит высоту.
Принцип работы
— Данные хранятся только на нижнем уровне (в Node).
— Верхние уровни содержат Index — указатели для быстрого прыжка.
— При вставке элемента случайно определяется высота (вероятность ~50% для каждого уровня).
— Максимальная высота ограничена 64 уровнями.
🔎 get(K key) — поиск
1. Начинается с верхнего уровня HeadIndex.
2. Движется вправо, пока ключ не станет больше искомого.
3. Спускается на уровень ниже.
4. Повторяет до нижнего уровня → O(log n).
5. Без блокировок, читает volatile-ссылки.
➕ put(K key, V value) — вставка
1. Выполняется поиск позиции (как в get).
2. Если ключ существует, обновляется через CAS → O(log n).
3. Если новый:
— Создаётся новый Node.
— Вставляется в нижний уровень с CAS.
— Случайно генерируется высота (геометрическое распределение).
— Создаются Index-узлы для верхних уровней.
— Связываются с соседями через CAS.
4. При необходимости увеличивается высота всей структуры.
Блокировки: минимальны, только при изменении указателей через CAS-retry loops.
➖ remove(Object key) — удаление
1. Находится узел на нижнем уровне.
2. Помечается как удалённый (marker node) через CAS.
3. Физически отсоединяется от списка.
4. Индексы на верхних уровнях удаляются постепенно (ленивое удаление).
5. Если верхние уровни опустели, высота уменьшается.
⚖️ Важные нюансы
1. Вероятностная балансировка
В отличие от AVL/Red-Black деревьев, балансировка достигается случайной высотой узлов.
Нет гарантии идеального баланса, но ожидаемая сложность O(log n).
2. Null и сравнения
Null ключи запрещены (NullPointerException).
Null значения допустимы (в отличие от ConcurrentHashMap).
Ключи должны быть Comparable или нужен Comparator.
3. Memory Consistency
Гарантии happens-before для put/get одного и того же ключа.
Weakly consistent bulk операции (putAll, clear).
— Упорядоченных concurrent-карт: логи по времени, рейтинги, приоритетные кэши.
— Range-запросы: subMap(from, to), headMap(to), tailMap(from).
— Навигация: firstEntry(), lastEntry(), floorEntry(key), ceilingEntry(key).
— Concurrent sorted set: keySet() даёт ConcurrentNavigableSet.
— Когда нужен порядок + потокобезопасность без глобальных блокировок.
Ставьте 🔥, если хотите ещё разбор.
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍4❤2
Наткнулся недавно на пост про винду, очень удивился, что после закрытия поддержки десятки народ массово переходит обратно на семёрку 😳
Думал будут прыгать на одиннадцатую или *nix системы.
#DevLife
Please open Telegram to view this post
VIEW IN TELEGRAM
😁8👍1🔥1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁27👍5🔥2🥱1
Forwarded from Библиотека собеса по Java | вопросы с собеседований
Iterable — это
Iterator — это
Цикл for-each — это
#core
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤3🔥1
🎁 Конкурс от Proglib Academy!
Кстати, если кто-то ещё не в курсе — у нас тут раздают MacBook Pro 14.
Да-да, не шутка, настоящий, железный, с M3 Pro
Но! Чтобы успеть пройти 2 недели обучения к 15 ноября, курс нужно взять до конца октября — и сейчас на всё скидка 40%.
Чтобы поучаствовать, нужно:
1️⃣ Покупаешь любой курс до конца октября;
2️⃣ Проходишь 2 недели обучения к 15 ноября;
3️⃣ Написать куратору в чат #розыгрыш.
До 15 ноября, потом всё — поезд (и макбук) уйдёт.
👉 Участвовать в розыгрыше
Кстати, если кто-то ещё не в курсе — у нас тут раздают MacBook Pro 14.
Да-да, не шутка, настоящий, железный, с M3 Pro
Но! Чтобы успеть пройти 2 недели обучения к 15 ноября, курс нужно взять до конца октября — и сейчас на всё скидка 40%.
Чтобы поучаствовать, нужно:
1️⃣ Покупаешь любой курс до конца октября;
2️⃣ Проходишь 2 недели обучения к 15 ноября;
3️⃣ Написать куратору в чат #розыгрыш.
До 15 ноября, потом всё — поезд (и макбук) уйдёт.
👉 Участвовать в розыгрыше
Please open Telegram to view this post
VIEW IN TELEGRAM
😁17💯3👍1🔥1
В Java 21 появились Virtual Threads — легковесные потоки, которые позволяют писать синхронный код с производительностью асинхронного.
По сути, это JVM-управляемые потоки (а не OS-потоки), которых можно создавать миллионы без значительных затрат памяти. Они решают главную проблему масштабирования традиционных потоков.
🔹 Зачем они нужны
Классические Platform Threads имеют проблемы:
— дорогие в создании (~1MB стека на поток);
— ограничены числом (~тысячи потоков максимум);
— при блокировке (IO, sleep) поток простаивает, занимая ресурсы.
Virtual Threads весят ~1KB, создаются мгновенно, и при блокировке платформенного потока освобождается для других задач. Это позволяет обрабатывать миллионы конкурентных запросов.
🔹 Ключевые моменты
▪️ Thread.ofVirtual() — создание билдера для virtual thread.
▪️ Thread.startVirtualThread() — быстрый старт задачи.
▪️ Executors.newVirtualThreadPerTaskExecutor() — пул для каждой задачи создаёт новый VT.
▪️ Автоматическое отсоединение от платформенного потока при блокировке (IO, sleep, wait, park).
▪️ Присоединение к платформенным потокам из ForkJoinPool.
🔹 Под капотом
Когда виртуальный поток блокируется (например, на IO), он "отцепляется" от платформенного потока. Освободившийся платформенный поток берёт другой готовый виртуальный поток. Когда операция завершается, виртуальный поток "подцепляется" обратно к доступному платформенному потоку.
🔹 Подводные камни
— Pinning (закрепление)
Virtual thread может "застрять" на платформенном потоке при:
• Synchronized блоках
• Нативных методах (JNI)
В таких случаях carrier thread блокируется вместе с virtual thread. Решение: использовать ReentrantLock вместо synchronized.
— ThreadLocal может быть опасен
Миллионы virtual threads с ThreadLocal приведут к огромному потреблению памяти. Используйте ScopedValue (preview feature в Java 21+).
— Не подходит для CPU-bound задач
Virtual threads оптимизированы для IO-bound операций. Для вычислений лучше параллельные стримы или ForkJoinPool.
— Мониторинг
Стандартные инструменты мониторинга потоков могут показывать некорректные данные — они заточены под platform threads.
— Высоконагруженные web-серверы с множеством конкурентных запросов.
— Микросервисы с большим количеством внешних вызовов (HTTP, БД).
— Когда нужна простота синхронного кода без сложности реактивного.
— Замена больших thread pools для IO-операций.
— CPU-intensive вычисления (сортировки, криптография).
— Код с большим количеством synchronized блоков (pinning).
— Легаси-код с активным использованием ThreadLocal.
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥3❤1💯1