Java Portal | Программирование
12.7K subscribers
1.26K photos
104 videos
38 files
1.22K links
Присоединяйтесь к нашему каналу и погрузитесь в мир для Java-разработчика

Связь: @devmangx

РКН: https://clck.ru/3H4WUg
Download Telegram
Пессимистическая vs оптимистическая блокировка

Частый вопрос на собеседованиях по backend.

[Пессимистическая блокировка]: -

- Запись недоступна другим потокам, пока текущий поток не закончит с ней работу.
- Даже чтение данных другими потоками невозможно, пока блокировка не снята.
- Пример: EntityManager.lock(entity, LockModeType.PESSIMISTIC_WRITE) в JPA.
- Минусы: снижает производительность при высоком уровне конкуренции.
- Когда использовать: когда критически важна точность данных.

[Оптимистическая блокировка]: -

- Не блокирует данные при чтении, но при сохранении проверяет версию записи.
- Пример: аннотация @Version в JPA (колонка для хранения версии).
- Если версия изменилась другим потоком, выбрасывается OptimisticLockException.
- Минусы: нужно разруливать конфликты.
- Когда использовать: когда чтений много, а вероятность конфликтов низкая.

Какой подход ты чаще используешь в своих проектах?

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Задумывался, как работают ActiveMQ и RabbitMQ?

В основе у них producer/consumer паттерн.

Как его реализовать?

Это базовая схема обмена данными между несколькими потоками. Поток-продюсер отправляет объекты на условную обработку, а потоки-консьюмеры асинхронно их получают и обрабатывают.

Общий вид решения такой:

продюсер кладет объекты в специальную коллекцию, буфер. Когда консьюмер освобождается, он запрашивает из буфера один объект. Если буфер пустой, консьюмер блокируется и ждёт; если буфер переполнен, ждёт продюсер.

Реализовать этот паттерн можно по-разному.

Самый правильный способ для продакшена: брать готовую реализацию из стандартной библиотеки, например BlockingQueue.

На собеседованиях обычно просят написать реализацию с нуля. На картинке показан один из вариантов.

Модификатор synchronized гарантирует, что в один момент времени выполняется только один из методов и только одним потоком. Этого достаточно для корректной работы, пока буфер не пуст и не переполнен. Когда буфер пустой или полный, управление явно передаётся продюсеру или консьюмеру соответственно через notify() и wait().

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
3
Почему твой бэкенд начинает тупить на 10k юзеров, хотя на 100 всё летало

Обычно причина одна из этих:

1️⃣N+1 запросы
→ один запрос незаметно триггерит сотню походов в БД

2️⃣Нет индексов
→ на каждом поиске полный проход по таблице

3️⃣Тяжелая работа синхронно
→ письма, обработка картинок прямо внутри request cycle

4️⃣Нет стратегии кеширования
→ один и тот же запрос в БД выполняется 1000 раз

5️⃣Единая точка отказа
→ один инстанс БД тащит на себе вообще всё

Приложение не стало внезапно медленным.
Оно просто доросло до момента, когда плохие решения стали заметны.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥92
Совет по Java: Stream.toArray(Type[]::new) это аккуратный и типобезопасный способ получить массив из стрима.

Избавляет от Object[] и ручных кастов.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍52
Вопрос для интервью по Java Spring Boot: @Transactional + @EventListener

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

[Дано]:
Команда написала логику отправки письма после регистрации пользователя. На проде иногда бывает ситуация: письма приходят, а пользователя в базе нет. Найди проблему и почини:

[Задачи]:

- Объясни, в каком сценарии письмо будет отправлено, но пользователь не сохранится
- Исправь код так, чтобы событие обрабатывалось только после того, как пользователь сохранён

Код:

@Service

@RequiredArgsConstructor
public class UserService {

private final UserRepository userRepository;
private final ApplicationEventPublisher eventPublisher;


@Transactional

public void register(UserDto dto) {
User user = new User(https://dto.email());
https://userRepository.save(user);

eventPublisher.publishEvent(new UserRegisteredEvent(user));
}
}

@Component

@RequiredArgsConstructor
public class EmailListener {

private final EmailSender emailSender;
private final SomeOtherService someOtherService;


@EventListener

public void onUserRegistered(UserRegisteredEvent event) {
emailSender.sendWelcome(event.user().getEmail());
someOtherService.doSomething();
}
}


👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3