Частые вопросы на собеседовании Senior Java

На Senior спрашивают не определения, а границы и trade-off'ы: почему parallelStream душит общий пул, когда брать свой ForkJoinPool, а когда virtual threads, чем shared Random проигрывает ThreadLocalRandom. Ниже — такие вопросы с ответами (многопоточность, Java Core, тесты) и разборы Senior-собесов по компаниям — большинство из них в JavaJub Pro.

Вопросы с ответами

Тестирование

Главный плюс constructor injection в тестах?

Ключевой плюс constructor injection для юнит-тестов — независимость от Spring-контекста: объект создаётся обычным new с переданными моками, без подъёма контейнера, что радикально ускоряет тысячи тестов. @MockBean как раз ТРЕБУЕТ контекста (это медленный интеграционный путь), final-поля не ускоряют Mockito, а возможность менять зависимости сеттерами — это минус field/setter injection, а не плюс конструктора.

полный разбор →
Java Core

Зачем RandomGenerator вместо Random?

RandomGenerator (JEP 356, Java 17) — это общий интерфейс для разных алгоритмов ГСЧ (Xoshiro, LXM-семейство L64X/L128X и др.), позволяющий выбирать генератор по нужным свойствам (период, splittable, jumpable, leapable) через RandomGeneratorFactory. Ловушки: он не про потокобезопасность и не про криптостойкость — для секретов по-прежнему нужен SecureRandom, а Random/ThreadLocalRandom стали лишь реализациями этого интерфейса.

полный разбор →
Многопоточность

Как java.util.Random становится thread-safe?

В java.util.Random поле seed — это AtomicLong, а метод next() в цикле читает старое значение и через compareAndSet атомарно записывает новое, повторяя попытку при конфликте; так достигается формально заявленная в Javadoc потокобезопасность без блокировок. Ловушка: используется неблокирующий CAS, а не synchronized; volatile сам по себе не защищает от гонки read-modify-write, а ThreadLocal-вариант — это уже отдельный класс ThreadLocalRandom.

полный разбор →
Многопоточность

Как устроен ThreadLocalRandom?

Ключевая идея ThreadLocalRandom — отсутствие разделяемого состояния: seed лежит прямо в полях самого Thread (threadLocalRandomSeed и др.), padding-поля снижают false sharing, и обновление seed идёт без CAS и без синхронизации. Поэтому неверны варианты с общим seed под локом или CAS, а также с обёрткой ThreadLocal<Random> — это специальная JVM-оптимизация, а не обычный ThreadLocal и не один генератор на всех.

полный разбор →
Многопоточность

Когда использовать что — Random, SecureRandom, ThreadLocalRandom?

Random годится для однопоточной несекретной случайности, ThreadLocalRandom — для многопоточной несекретной (нет contention на общий seed), а SecureRandom — для криптографии (токены, пароли, соль), но он медленнее. Ловушки: общий Random в многопотоке хоть и synchronized, но создаёт contention и проигрывает ThreadLocalRandom; ThreadLocalRandom НЕ криптостоек; SecureRandom не быстрее и не замена обычному Random для произвольной случайности.

полный разбор →
Многопоточность

Когда что выбирать — свой ForkJoinPool или virtual threads?

ForkJoinPool с размером ~числа ядер — для CPU-bound (математика, парсинг, трансформации без IO), а virtual threads — для IO-bound: они дёшевы и при блокировке на JDBC/HTTP отпускают несущий поток.

полный разбор →
Java Core

Почему final-поля и constructor injection — стандарт Senior?

Стандарт — иммутабельность зависимостей: после создания singleton-сервиса его зависимости не должны меняться, и final это гарантирует на уровне компилятора, что и лежит в основе thread-safety. Конструктор делает зависимости явными и проверяемыми.

полный разбор →
Многопоточность

Почему .parallel() — проблема?

Главная беда parallel() — все параллельные стримы делят один общий ForkJoinPool.commonPool() на всю JVM, поэтому одна блокирующая или тяжёлая задача душит остальные, а размер пула фиксирован числом ядер. Ловушка: новый пул на каждый вызов не создаётся, порядок для корректно ассоциативных reduce сохраняется (forEachOrdered/collect это учитывают), и поэлементной сериализации нет — речь о разделяемом ресурсе и блокировках в нём.

полный разбор →
Java Core

Почему shared Random может быть медленнее sequential?

java.util.Random обновляет seed через CAS в цикле: при конкуренции только один поток из семи успевает, остальные крутят retry, и contention сводит на нет параллелизм. Ловушка: методы Random.next() не synchronized (там как раз lock-free CAS на AtomicLong), false sharing не главная причина, а дубликатов чисел не возникает — проигрыш именно в повторяющихся неуспешных CAS.

полный разбор →
Многопоточность

На code review найден shared java.util.Random внутри parallelStream. Какой комментарий наиболее полезен?

У shared Random есть синхронизация/CAS на общем состоянии. В параллельной обработке это может убить выигрыш от parallelStream.

полный разбор →

Разборы Senior-собесов по компаниям

Что реально спрашивают на Senior в конкретных компаниях — с задачами, System Design и live-coding. Бесплатные разборы открываются сразу, остальные — в JavaJub Pro (там можно заглянуть в содержание).

Больше Senior-вопросов — в канале

Новые senior-вопросы, разборы System Design и live-coding выходят в Telegram первыми. А проверить себя можно тестами и флешкартами.

Senior-вопросы в Telegram Пройти тест Резюме под Senior
› новые гайды и свежие вопросы с собесов — первыми в Telegram Смотреть гайды Подписаться