This media is not supported in your browser
VIEW IN TELEGRAM
Терминальный интерфейс для Docker на Rust
Приложение позволяет просматривать и управлять контейнерами, образами, томами и сетями прямо из терминала, вдохновлено K9s и делает работу с Docker быстрее и удобнее.
Репозиторий на GitHub
👉 Java Portal
Приложение позволяет просматривать и управлять контейнерами, образами, томами и сетями прямо из терминала, вдохновлено K9s и делает работу с Docker быстрее и удобнее.
Репозиторий на GitHub
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5
Вопросы по Java + Spring Boot на собеседованиях (сценарии из реальной практики)
Ниже приведены несколько типичных сценариев с короткими ответами (TL;DR — можно сохранить для повторения перед интервью):
🔸 Типы Spring-бинов и стереотипы
Сценарий: Представь, что ты проектируешь сложную e-commerce платформу. Где ты используешь интерфейс с аннотацией
→
🔸 Циклические зависимости
Сценарий: Коллега добавил новую фичу, и теперь твое Spring-приложение не стартует, выдавая BeanCurrentlyInCreationException из-за циклической зависимости между ServiceA и ServiceB.
Предположим, что быстро переработать бизнес-логику невозможно. Какое минимальное изменение кода ты бы предложил, чтобы приложение хотя бы запустилось, и почему это считается временным решением?
→
Spring по умолчанию может использовать проксирование и конструкторную/сеттерную инъекцию.
Лучшее решение — перепроектировать зависимости или использовать
🔸 Распространение транзакций
Сценарий: У тебя есть OrderService с методом createOrder(), помеченным
Внутри он вызывает updateInventory() (тоже в OrderService и тоже с
Если updateInventory() выбрасывает runtime-исключение, что произойдет с транзакцией, начатой в createOrder()?
Как изменить дизайн, если нужно, чтобы оба метода выполнялись в отдельных, независимых транзакциях?
→
Транзакция не будет распространяться (прокси не сработает при внутреннем вызове).
Решение — self-injection (внедрение самого себя как зависимости) или использование AOP.
🔸 Скоупы бинов
Сценарий: Нужно хранить товары пользователя в корзине и управлять временным списком поисковых фильтров, который очищается после каждого HTTP-запроса.
Какой скоуп ты выберешь для ShoppingCart и какой — для SearchFilter, и почему?
→
🔸 Controller Advice
Сценарий: В приложении есть и традиционные веб-эндпоинты с Thymeleaf, и REST API.
Нужно централизовать обработку ошибок (например, перехват ResourceNotFoundException):
Как вернуть страницу 404 для обычных web-эндпоинтов?
Как вернуть JSON с ошибкой 404 для REST API?
→
🔸 Автоконфигурация
Сценарий: Ты добавил в проект стороннюю библиотеку (например, кастомный логгер) и просто положил её JAR в classpath.
Без написания конфигурационных классов Spring автоматически подхватывает нужные бины.
Объясни, как Spring Boot определяет и подключает их при старте.
→
Использует SpringFactoriesLoader, который читает META-INF/spring.factories и конфигурирует бины в зависимости от содержимого classpath.
🔸 Ограничение частоты запросов
Сценарий: Твой публичный API перегружен — один клиент шлет слишком много запросов, мешая остальным.
Какой практичный, независимый от технологий подход можно применить для ограничения, например, 100 запросов в минуту на клиента, и где обычно реализуется такая логика?
→
Bucket4j / Resilience4j, счетчики в Redis, лимитирование на уровне API Gateway.
🔸 Распределённые транзакции
Сценарий: В микросервисной архитектуре оформление заказа включает два шага — списание товара в Inventory Service и списание денег через Payment Service.
Если списание товара прошло успешно, а оплата — нет, какой шаблон проектирования поможет откатить изменения в Inventory и обеспечить согласованность данных?
→
Шаблон Saga (хореография или оркестрация), либо двухфазный коммит (2PC, но редко используется на практике).
👉 Java Portal
Ниже приведены несколько типичных сценариев с короткими ответами (TL;DR — можно сохранить для повторения перед интервью):
Сценарий: Представь, что ты проектируешь сложную e-commerce платформу. Где ты используешь интерфейс с аннотацией
@Repository
, а где — с аннотацией @Service? Приведи конкретный пример, какую роль каждая из этих аннотаций играет в процессе оформления заказа пользователем.→
@Component
— универсальный бин,@Service
— бизнес-логика,@Repository
— DAO + перевод исключений в DataAccessException,@Controller
— контроллер уровня MVC.Сценарий: Коллега добавил новую фичу, и теперь твое Spring-приложение не стартует, выдавая BeanCurrentlyInCreationException из-за циклической зависимости между ServiceA и ServiceB.
Предположим, что быстро переработать бизнес-логику невозможно. Какое минимальное изменение кода ты бы предложил, чтобы приложение хотя бы запустилось, и почему это считается временным решением?
→
Spring по умолчанию может использовать проксирование и конструкторную/сеттерную инъекцию.
Лучшее решение — перепроектировать зависимости или использовать
@Lazy
.Сценарий: У тебя есть OrderService с методом createOrder(), помеченным
@Transactional
.Внутри он вызывает updateInventory() (тоже в OrderService и тоже с
@Transactional
).Если updateInventory() выбрасывает runtime-исключение, что произойдет с транзакцией, начатой в createOrder()?
Как изменить дизайн, если нужно, чтобы оба метода выполнялись в отдельных, независимых транзакциях?
→
Транзакция не будет распространяться (прокси не сработает при внутреннем вызове).
Решение — self-injection (внедрение самого себя как зависимости) или использование AOP.
Сценарий: Нужно хранить товары пользователя в корзине и управлять временным списком поисковых фильтров, который очищается после каждого HTTP-запроса.
Какой скоуп ты выберешь для ShoppingCart и какой — для SearchFilter, и почему?
→
@SessionScope
— для корзины (привязано к пользовательской сессии),@RequestScope
— для поискового фильтра (новый бин на каждый HTTP-запрос).Сценарий: В приложении есть и традиционные веб-эндпоинты с Thymeleaf, и REST API.
Нужно централизовать обработку ошибок (например, перехват ResourceNotFoundException):
Как вернуть страницу 404 для обычных web-эндпоинтов?
Как вернуть JSON с ошибкой 404 для REST API?
→
@ControllerAdvice
— используется с @Controller
, возвращает view.@RestControllerAdvice
— сочетает @ControllerAdvice
+ @ResponseBody (для REST API).Сценарий: Ты добавил в проект стороннюю библиотеку (например, кастомный логгер) и просто положил её JAR в classpath.
Без написания конфигурационных классов Spring автоматически подхватывает нужные бины.
Объясни, как Spring Boot определяет и подключает их при старте.
→
Использует SpringFactoriesLoader, который читает META-INF/spring.factories и конфигурирует бины в зависимости от содержимого classpath.
Сценарий: Твой публичный API перегружен — один клиент шлет слишком много запросов, мешая остальным.
Какой практичный, независимый от технологий подход можно применить для ограничения, например, 100 запросов в минуту на клиента, и где обычно реализуется такая логика?
→
Bucket4j / Resilience4j, счетчики в Redis, лимитирование на уровне API Gateway.
Сценарий: В микросервисной архитектуре оформление заказа включает два шага — списание товара в Inventory Service и списание денег через Payment Service.
Если списание товара прошло успешно, а оплата — нет, какой шаблон проектирования поможет откатить изменения в Inventory и обеспечить согласованность данных?
→
Шаблон Saga (хореография или оркестрация), либо двухфазный коммит (2PC, но редко используется на практике).
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍5
Как правильно обрабатывать ошибки в Spring Boot REST
Если ты делаешь REST-API на Spring Boot, важно не просто ловить исключения, а возвращать понятные ответы клиенту. Корректные HTTP-коды и осмысленные сообщения помогают быстрее понять, что пошло не так — будь то дубликаты записей, ошибки валидации или проблемы с аутентификацией.
В статье объясняется, как организовать централизованную обработку ошибок, какие статусы стоит использовать (400, 401, 404, 409, 500 и т.д.), и почему логирование играет ключевую роль в поддержке и быстром устранении проблем в проде.
Подробнее тут
👉 Java Portal
Если ты делаешь REST-API на Spring Boot, важно не просто ловить исключения, а возвращать понятные ответы клиенту. Корректные HTTP-коды и осмысленные сообщения помогают быстрее понять, что пошло не так — будь то дубликаты записей, ошибки валидации или проблемы с аутентификацией.
В статье объясняется, как организовать централизованную обработку ошибок, какие статусы стоит использовать (400, 401, 404, 409, 500 и т.д.), и почему логирование играет ключевую роль в поддержке и быстром устранении проблем в проде.
Подробнее тут
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4❤1🌚1💊1
Ты правильно используешь коллекции в Java?
Не все коллекции одинаково полезны, и неправильный выбор может увеличить нагрузку на CPU или память в 10 раз, даже не замечая этого. Если работаешь с большими коллекциями, это важно:
1. ArrayList
Идеально, когда:
Читаешь много, а пишешь мало.
Доступ к элементам по позиции (get(i)).
Почему? Внутри — массив. Чтение очень быстрое, но вставка или удаление в середине медленные, потому что нужно сдвигать элементы.
Используй для: каталогов, списков, которые почти не меняются, или результатов, которые создаются один раз и потом только читаются.
2. LinkedList
Идеально, когда:
Постоянно добавляешь или удаляешь элементы.
Не нужен прямой доступ к элементу по индексу.
Каждый элемент знает, кто перед ним и кто после, поэтому вставка/удаление быстрые, но поиск конкретного элемента медленный, так как нужно проходить список поэлементно.
Используй для: очередей, буферов или структур, где важен порядок, а не скорость доступа.
3. HashMap
Идеально, когда:
Нужно хранить пары ключ/значение.
Требуется быстрый доступ по ключу (как словарь).
Использует функцию хеширования для быстрого поиска. Если hashCode() реализован плохо, может работать медленно и потреблять больше памяти.
Используй для: хранения пользователей, продуктов, настроек или любых данных, к которым нужен быстрый доступ по ключу.
Перед оптимизацией спроси себя:
Много читаю и мало пишу? → ArrayList
Часто вставляю/удаляю? → LinkedList
Ищу по ключу? → HashMap
Нет универсально «лучшей» структуры. Есть та, которая подходит под твой способ доступа к данным.
👉 Java Portal
Не все коллекции одинаково полезны, и неправильный выбор может увеличить нагрузку на CPU или память в 10 раз, даже не замечая этого. Если работаешь с большими коллекциями, это важно:
1. ArrayList
Идеально, когда:
Читаешь много, а пишешь мало.
Доступ к элементам по позиции (get(i)).
Почему? Внутри — массив. Чтение очень быстрое, но вставка или удаление в середине медленные, потому что нужно сдвигать элементы.
Используй для: каталогов, списков, которые почти не меняются, или результатов, которые создаются один раз и потом только читаются.
2. LinkedList
Идеально, когда:
Постоянно добавляешь или удаляешь элементы.
Не нужен прямой доступ к элементу по индексу.
Каждый элемент знает, кто перед ним и кто после, поэтому вставка/удаление быстрые, но поиск конкретного элемента медленный, так как нужно проходить список поэлементно.
Используй для: очередей, буферов или структур, где важен порядок, а не скорость доступа.
3. HashMap
Идеально, когда:
Нужно хранить пары ключ/значение.
Требуется быстрый доступ по ключу (как словарь).
Использует функцию хеширования для быстрого поиска. Если hashCode() реализован плохо, может работать медленно и потреблять больше памяти.
Используй для: хранения пользователей, продуктов, настроек или любых данных, к которым нужен быстрый доступ по ключу.
Перед оптимизацией спроси себя:
Много читаю и мало пишу? → ArrayList
Часто вставляю/удаляю? → LinkedList
Ищу по ключу? → HashMap
Нет универсально «лучшей» структуры. Есть та, которая подходит под твой способ доступа к данным.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11❤4
Please open Telegram to view this post
VIEW IN TELEGRAM
❤17🤣2
This media is not supported in your browser
VIEW IN TELEGRAM
Gitvizz превращает код в интерактивный граф
Терялся в собственном коде?
Встречай Gitvizz — инструмент, который мгновенно превращает кодовую базу в интерактивные графы, чтобы наглядно увидеть, как всё связано.
Посмотреть можно на gitvizz.com
👉 Java Portal
Терялся в собственном коде?
Встречай Gitvizz — инструмент, который мгновенно превращает кодовую базу в интерактивные графы, чтобы наглядно увидеть, как всё связано.
Посмотреть можно на gitvizz.com
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6👍4
Что такое String Pool
String Pool → это специальная область памяти внутри heap, где Java хранит строковые литералы.
Главная идея → повторное использование строк и экономия памяти.
Как это работает:
s1 и s2 указывают на один и тот же объект в String Pool → дубликаты не создаются.
Но если сделать так:
new String() обходит пул и создаёт новый объект в heap.
Зачем это нужно:
→ Экономит память за счёт переиспользования неизменяемых строк.
→ Повышает производительность при повторных строковых значениях.
→ Безопасно для потоков, потому что строки immutable.
Как заставить строку из heap использовать пул?
Ответ:
Метод intern() → добавляет строку в пул и возвращает ссылку на объект из пула.
👉 Java Portal
String Pool → это специальная область памяти внутри heap, где Java хранит строковые литералы.
Главная идея → повторное использование строк и экономия памяти.
Как это работает:
String s1 = "Java";
String s2 = "Java";
System.out.println(s1 == s2); // true
s1 и s2 указывают на один и тот же объект в String Pool → дубликаты не создаются.
Но если сделать так:
String s3 = new String("Java");
System.out.println(s1 == s3); // false
new String() обходит пул и создаёт новый объект в heap.
Зачем это нужно:
→ Экономит память за счёт переиспользования неизменяемых строк.
→ Повышает производительность при повторных строковых значениях.
→ Безопасно для потоков, потому что строки immutable.
Как заставить строку из heap использовать пул?
Ответ:
s3 = s3.intern();
Метод intern() → добавляет строку в пул и возвращает ссылку на объект из пула.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤5
Топ-20 вопросов по микросервисам для Java-разработчиков
На Java67 вышла подборка самых частых вопросов по микросервисной архитектуре — от отличий монолита до тем вроде Docker, Kubernetes, API Gateway, CQRS и Saga-паттернов.
👉 Java Portal
На Java67 вышла подборка самых частых вопросов по микросервисной архитектуре — от отличий монолита до тем вроде Docker, Kubernetes, API Gateway, CQRS и Saga-паттернов.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5👍2🤔1
Сценарный вопрос с реального интервью по Java/Spring Boot:
В контроллере вызывается метод сервиса, помеченный аннотацией
Этот метод не только сохраняет сущность, но и отправляет два письма: одно администратору, другое — пользователю, который сделал запрос.
Класс, отвечающий за отправку почты, помечен аннотацией
В итоге API обрабатывает запрос целых 12 секунд — очевидно, это неприемлемо.
Вопрос: почему так происходит и как это исправить?
Реальная причина:
Когда используется
Если внутри этого же контекста вызывается
Иными словами, асинхронный код оказывается «заперт» внутри транзакции.
В результате, коммит в базу ждёт, пока оба письма не будут отправлены.
Как исправить:
Заменить прямой вызов отправки писем на event-publisher подход.
После сохранения запроса просто опубликовать событие, например DemoRequestCreatedEvent.
Асинхронные слушатели (
Что получаем:
Транзакция завершается за ~100 мс вместо 12 секунд.
API реагирует почти мгновенно.
Письма всё так же надёжно уходят в фоне.
Использование событий и асинхронных слушателей — не просто красивая архитектурная штука, а реальный способ сделать систему быстрой, масштабируемой и профессиональной.
Дополнительный вопрос:
Кроме событий, какие подходы ты используешь, чтобы отделить транзакционную логику (например, коммит в БД) от побочных эффектов вроде отправки писем или уведомлений?
@Java_Iibrary
В контроллере вызывается метод сервиса, помеченный аннотацией
@Transactional
.Этот метод не только сохраняет сущность, но и отправляет два письма: одно администратору, другое — пользователю, который сделал запрос.
Класс, отвечающий за отправку почты, помечен аннотацией
@Async
, но Spring всё равно выполняет его синхронно.В итоге API обрабатывает запрос целых 12 секунд — очевидно, это неприемлемо.
Вопрос: почему так происходит и как это исправить?
Реальная причина:
Когда используется
@Transactional
, Spring создаёт прокси для транзакции.Если внутри этого же контекста вызывается
@Async
-метод, то Spring не создаёт новый поток — потому что вызов происходит внутри того же прокси.Иными словами, асинхронный код оказывается «заперт» внутри транзакции.
В результате, коммит в базу ждёт, пока оба письма не будут отправлены.
Как исправить:
Заменить прямой вызов отправки писем на event-publisher подход.
После сохранения запроса просто опубликовать событие, например DemoRequestCreatedEvent.
Асинхронные слушатели (
@EventListener
+ @Async
) будут обрабатывать отправку писем вне основной транзакции.Что получаем:
Транзакция завершается за ~100 мс вместо 12 секунд.
API реагирует почти мгновенно.
Письма всё так же надёжно уходят в фоне.
Использование событий и асинхронных слушателей — не просто красивая архитектурная штука, а реальный способ сделать систему быстрой, масштабируемой и профессиональной.
Дополнительный вопрос:
Кроме событий, какие подходы ты используешь, чтобы отделить транзакционную логику (например, коммит в БД) от побочных эффектов вроде отправки писем или уведомлений?
@Java_Iibrary
👍9❤2
This media is not supported in your browser
VIEW IN TELEGRAM
Хочешь сделать крутой GitHub-профиль?
На этом сайте собраны десятки классных README от разработчиков со всего мира. Можно смотреть код, вдохновляться, подхватывать идеи и оформить свой профиль так, чтобы он реально выделялся.
github.com/zzetao/awesome-github-profile
👉 Java Portal
На этом сайте собраны десятки классных README от разработчиков со всего мира. Можно смотреть код, вдохновляться, подхватывать идеи и оформить свой профиль так, чтобы он реально выделялся.
github.com/zzetao/awesome-github-profile
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍3
В Java есть одно зарезервированное слово, которое многие не замечают — yield.
Оно появилось в Java 13 вместе с switch expressions.
yield используется, чтобы вернуть значение из блока case, когда нужно выполнить несколько действий перед тем, как определить результат.
Пример:
yield — не то же самое, что break:
break просто прерывает выполнение;
yield возвращает значение блока в switch, который используется как выражение.
🌟
👉 Java Portal
Оно появилось в Java 13 вместе с switch expressions.
yield используется, чтобы вернуть значение из блока case, когда нужно выполнить несколько действий перед тем, как определить результат.
Пример:
int day = 2;
String result = switch (day) {
case 1 -> "Понедельник";
case 2 -> {
System.out.println("Обработка...");
yield "Вторник"; // значение, которое возвращается
}
default -> "Другой день";
};
yield — не то же самое, что break:
break просто прерывает выполнение;
yield возвращает значение блока в switch, который используется как выражение.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤6
15 октября(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика.
Как это будет:
Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot
Реклама.
О рекламодателе.
Please open Telegram to view this post
VIEW IN TELEGRAM
Шаг за шагом проектируем сокращатель ссылок
В статье разбираем System Design на реальном примере = создаем свой сервис сокращения ссылок. Это классическая задача, которую часто дают на собеседованиях, и при этом отличная возможность понять, как устроен процесс проектирования систем: от постановки задачи до расчёта нагрузки и продумывания архитектуры.
👉 Java Portal
В статье разбираем System Design на реальном примере = создаем свой сервис сокращения ссылок. Это классическая задача, которую часто дают на собеседованиях, и при этом отличная возможность понять, как устроен процесс проектирования систем: от постановки задачи до расчёта нагрузки и продумывания архитектуры.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4
В Spring Boot можно включить «мягкое» завершение приложения, добавив в конфиг строку: "
Это помогает избежать типичных проблем при остановке сервиса:
- Активные HTTP-запросы обрываются посреди выполнения
- Транзакции в базе откатываются неожиданно
- Потоки прерываются до завершения работы
👉 Java Portal
server.shutdown=graceful
" server:
shutdown: graceful
spring:
lifecycle:
timeout-per-shutdown-phase: 20s
# Сервер будет завершать работу корректно
# Он даст до 20 секунд на завершение всех запросов и бинов.
Это помогает избежать типичных проблем при остановке сервиса:
- Активные HTTP-запросы обрываются посреди выполнения
- Транзакции в базе откатываются неожиданно
- Потоки прерываются до завершения работы
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11👀4
6.851 MIT: Продвинутые структуры данных (весна'21)
Этот курс давно был у меня в списке рекомендаций. Разбор темы иерархии памяти там отлично подан в контексте cache-oblivious алгоритмов.
https://courses.csail.mit.edu/6.851/spring21/
👉 Java Portal
Этот курс давно был у меня в списке рекомендаций. Разбор темы иерархии памяти там отлично подан в контексте cache-oblivious алгоритмов.
https://courses.csail.mit.edu/6.851/spring21/
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍2
Сборщик мусора (Garbage Collector, GC) сильно эволюционировал со временем. Сегодня есть несколько вариантов, и ты можешь выбрать тот, что подходит под твои нужды. Смотри:
- Serial GC (олдскул)
Самый простой и древний.
Один поток, останавливает всё приложение на время очистки памяти.
Подходит для мелких приложений, CLI-инструментов или систем с маленьким heap (пара десятков мегабайт).
- Parallel GC
По сути, тот же Serial, но работает в несколько потоков.
Паузы всё ещё есть, но они короче.
Хорош для batch-задач или сервисов, где короткая остановка не критична.
- G1 GC (Garbage First)
С Java 9 — сборщик по умолчанию.
Делит heap на регионы и чистит только самые “грязные”.
Даёт меньше пауз и предсказуемее поведение.
Оптимальный выбор для большинства продакшен-приложений: Spring, микросервисы и т. д.
- ZGC (Z Garbage Collector)
Паузы меньше 1 мс даже при heap в сотни гигабайт.
Работает почти полностью конкурентно, фактически в реальном времени.
Подходит для систем, которые не могут останавливаться: трейдинг, онлайн-игры, API с высокой доступностью.
- Shenandoah GC
Похож на ZGC, но реализован по-другому (Red Hat).
Тоже стремится к минимальным паузам, отлично чувствует себя на Linux.
Менее популярный, но стабильный вариант.
Что выбрать?
Небольшие приложения → Serial
Batch-процессы → Parallel
Веб-сервисы, микросервисы → G1
Реальное время, критичная задержка → ZGC или Shenandoah
GC уже давно не “та самая штука, что стопит Java”, а гибкий инструмент, который можно подобрать под задачу.
И от этого выбора реально зависит будет твое приложение тормозить… или летать
👉 Java Portal
- Serial GC (олдскул)
Самый простой и древний.
Один поток, останавливает всё приложение на время очистки памяти.
Подходит для мелких приложений, CLI-инструментов или систем с маленьким heap (пара десятков мегабайт).
- Parallel GC
По сути, тот же Serial, но работает в несколько потоков.
Паузы всё ещё есть, но они короче.
Хорош для batch-задач или сервисов, где короткая остановка не критична.
- G1 GC (Garbage First)
С Java 9 — сборщик по умолчанию.
Делит heap на регионы и чистит только самые “грязные”.
Даёт меньше пауз и предсказуемее поведение.
Оптимальный выбор для большинства продакшен-приложений: Spring, микросервисы и т. д.
- ZGC (Z Garbage Collector)
Паузы меньше 1 мс даже при heap в сотни гигабайт.
Работает почти полностью конкурентно, фактически в реальном времени.
Подходит для систем, которые не могут останавливаться: трейдинг, онлайн-игры, API с высокой доступностью.
- Shenandoah GC
Похож на ZGC, но реализован по-другому (Red Hat).
Тоже стремится к минимальным паузам, отлично чувствует себя на Linux.
Менее популярный, но стабильный вариант.
Что выбрать?
Небольшие приложения → Serial
Batch-процессы → Parallel
Веб-сервисы, микросервисы → G1
Реальное время, критичная задержка → ZGC или Shenandoah
GC уже давно не “та самая штука, что стопит Java”, а гибкий инструмент, который можно подобрать под задачу.
И от этого выбора реально зависит будет твое приложение тормозить… или летать
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤4
Transactions_and_Concurrency_Control.pdf
6.3 MB
Если ты работаешь с Java, очень советую почитать последнее издание “Troubleshooting Java”
В книге куча практических вещей: от лучших практик отладки до логирования, трейсинга, телеметрии, модели памяти Java, предотвращения дедлоков, профайлинга и сэмплинга.
Отличное чтиво, если хочешь реально понимать, что происходит под капотом JVM и как быстро находить проблемы в проде.
👉 Java Portal
В книге куча практических вещей: от лучших практик отладки до логирования, трейсинга, телеметрии, модели памяти Java, предотвращения дедлоков, профайлинга и сэмплинга.
Отличное чтиво, если хочешь реально понимать, что происходит под капотом JVM и как быстро находить проблемы в проде.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8
Может ли статический блок выбросить исключение?
У тебя есть класс, который инициализирует какой-то критически важный статический ресурс внутри статического блока. В процессе инициализации может произойти ошибка, и выбросится исключение. Что произойдет, если исключение будет выброшено из статического инициализатора? Какую ошибку в итоге выбросит JVM, и в каком состоянии останется класс после этого?
Подсказка → Если из статического блока выбрасывается исключение, инициализация класса завершается с ошибкой.
Есть ли в Java концепция выбрасывания исключений конструктором?
Ты создаешь класс DatabaseConnection. В конструкторе происходит попытка установить соединение с базой данных, и если это не удается, выбрасывается SQLException. Что произойдет с памятью, выделенной под объект DatabaseConnection, если конструктор выбросит исключение? Можно ли использовать объект после того, как исключение было выброшено?
Подсказка → Конструкторы могут (и часто должны) выбрасывать исключения, если объект невозможно создать в корректном состоянии.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤2
Хочешь учить и практиковать SQL без установки ничего на компьютер?
Есть классный ресурс и всё работает прямо в браузере.
Можно создавать базы MySQL и PostgreSQL, писать запросы и сразу видеть результат.
Бесплатно → http://sqlplayground.app
👉 Java Portal
Есть классный ресурс и всё работает прямо в браузере.
Можно создавать базы MySQL и PostgreSQL, писать запросы и сразу видеть результат.
Бесплатно → http://sqlplayground.app
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤2
Почему важно давать хорошие имена в коде?
Потому что большую часть времени мы не пишем код, а читаем его. И одно удачное имя способно объяснить то, что комментарий бы растянул на три строки.
Что решает хорошее имя:
Намерение: expireSession() говорит больше, чем process().
Контекст: calculatePriceWithTax() понятнее, чем просто calculate().
Контракт: isEmpty() (логический результат) и getSize() (число) — разное поведение, и имя это чётко показывает.
Простые, но работающие правила:
Глагол + объект для действий: sendInvoiceEmail().
Ясное существительное для данных: PaymentRequest, CustomerId.
Без тайнописи вроде cfg, mgr, tmp2.
Если логика нетривиальна, пусть имя объясняет “почему”: retryOnRateLimit().
А комментарии не нужны?🤔
Нужны, но точечно. Пиши их там, где код сам не может выразить мысль:
когда решение неочевидное;
когда нужна историческая справка или ссылка на ADR.
Главное не использовать комментарии, чтобы объяснять то, что код и так должен рассказывать сам.
👉 Java Portal
Потому что большую часть времени мы не пишем код, а читаем его. И одно удачное имя способно объяснить то, что комментарий бы растянул на три строки.
Что решает хорошее имя:
Намерение: expireSession() говорит больше, чем process().
Контекст: calculatePriceWithTax() понятнее, чем просто calculate().
Контракт: isEmpty() (логический результат) и getSize() (число) — разное поведение, и имя это чётко показывает.
Простые, но работающие правила:
Глагол + объект для действий: sendInvoiceEmail().
Ясное существительное для данных: PaymentRequest, CustomerId.
Без тайнописи вроде cfg, mgr, tmp2.
Если логика нетривиальна, пусть имя объясняет “почему”: retryOnRateLimit().
А комментарии не нужны?
Нужны, но точечно. Пиши их там, где код сам не может выразить мысль:
когда решение неочевидное;
когда нужна историческая справка или ссылка на ADR.
Главное не использовать комментарии, чтобы объяснять то, что код и так должен рассказывать сам.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤2