⚡️ Параллельные стримы: ускорение или нет?
Java предоставляет мощный инструмент для обработки данных — параллельные стримы. Они позволяют автоматически распределять вычисления по нескольким потокам, но их эффективность зависит от множества факторов.
Добавление parallelStream() бездумно — это не "оптимизация", а лотерея с шансом на баги и падение.
❌ Когда не использовать
— При небольшом наборе данных (<10 000 элементов) затраты на управление потоками могут превышать прирост скорости.
— Операции sorted(), distinct() или limit() требуют полного знания данных, что снижает эффективность параллельного выполнения.
— Вложенные parallelStream() в CompletableFuture или ExecutorService могут привести к конкуренции за ресурсы и неожиданному падению производительности.
✔️ Когда использовать
— Обработка больших объёмов данных (100 000+ элементов).
— Операции независимы и ресурсоёмки, например, сложные вычисления, парсинг файлов, загрузка данных из сети.
🔍 Важная особенность
parallelStream() использует ForkJoinPool.commonPool(). Если есть другие задачи, использующие этот же пул, они могут начать конкурировать за потоки, замедляя всё приложение.
💬 Делитесь в комментах интересными кейсами
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#CoreJava #лучшее2025
Java предоставляет мощный инструмент для обработки данных — параллельные стримы. Они позволяют автоматически распределять вычисления по нескольким потокам, но их эффективность зависит от множества факторов.
Добавление parallelStream() бездумно — это не "оптимизация", а лотерея с шансом на баги и падение.
— При небольшом наборе данных (<10 000 элементов) затраты на управление потоками могут превышать прирост скорости.
— Операции sorted(), distinct() или limit() требуют полного знания данных, что снижает эффективность параллельного выполнения.
— Вложенные parallelStream() в CompletableFuture или ExecutorService могут привести к конкуренции за ресурсы и неожиданному падению производительности.
— Обработка больших объёмов данных (100 000+ элементов).
— Операции независимы и ресурсоёмки, например, сложные вычисления, парсинг файлов, загрузка данных из сети.
parallelStream() использует ForkJoinPool.commonPool(). Если есть другие задачи, использующие этот же пул, они могут начать конкурировать за потоки, замедляя всё приложение.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#CoreJava #лучшее2025
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥2❤1👏1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁35👾7👍2🔥2🤩1
Запускаешь тесты, они зелёные, и ты думаешь всё ок? А потом баг на проде в ветке, которую никто не проверил. IDEA умеет показывать, что реально покрыто тестами.
🔹 Что это
Run with Coverage — запуск тестов с визуализацией покрытия кода. Видишь прямо в редакторе, какие строки покрыты тестами, а какие нет.
🔹 Как запустить
— Ctrl+Shift+F10 → выбрать "Run with Coverage".
— Или правой кнопкой на тест/класс → "More Run/Debug" → "Run with Coverage".
— Или через иконку щита рядом с кнопкой Run.
🔹 Что показывает
→ Зелёная полоска слева от кода — строка выполнилась.
→ Красная полоска — строка не покрыта тестами.
→ Жёлтая полоска — ветка покрыта частично (if выполнился, else — нет).
→ Окно Coverage — статистика по классам, пакетам, методам.
🔹 Фишки
→ Кликни на класс в Coverage window → увидишь его code coverage.
→ Кликни на жёлтую полоску → IDEA покажет, какая именно ветка не покрыта.
→ Сортируй классы по проценту покрытия — найдёшь слабые места.
→ Экспортируй отчёт (HTML) через кнопку в Coverage панели.
🔹 Зачем это нужно
— Находишь непокрытые edge cases.
— Видишь, что тест не проверяет все ветки if/else.
— Не гадаешь, а точно знаешь, что покрыто.
— Быстро понимаешь, где добавить тесты.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥4👏1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁34💯11🔥3🌚2😢1
Логи в проде — это не просто System.out.println(). Это структурированные данные, correlation ID, асинхронная запись и ротация. Разбираем настройку от А до Я.
Spring Boot из коробки использует Logback. Добавляем зависимости:
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>7.4</version>
</dependency>
ИЛИ
gradleimplementation 'net.logstash.logback:logstash-logback-encoder:7.4'
Это даст JSON-формат логов для удобного парсинга в ELK/Grafana.
Кладём в src/main/resources:
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<includeContext>false</includeContext>
<includeMdc>true</includeMdc>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/application.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>logs/application-%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>10GB</totalSizeCap>
</rollingPolicy>
<encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
</configuration>
Логи ротируются по размеру и времени, старые архивируются в gzip.
Создаём фильтр для трекинга запросов:
@Component
public class CorrelationIdFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) throws ServletException, IOException {
String correlationId = request.getHeader("X-Correlation-ID");
if (correlationId == null) {
correlationId = UUID.randomUUID().toString();
}
MDC.put("correlationId", correlationId);
response.setHeader("X-Correlation-ID", correlationId);
try {
chain.doFilter(request, response);
} finally {
MDC.clear();
}
}
}
Теперь каждый лог привязан к конкретному запросу. В JSON-логе будет поле correlationId.
logging:
level:
root: INFO
com.yourcompany: DEBUG
org.springframework.web: WARN
org.hibernate.SQL: DEBUG
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss} - %msg%n"
Для прода root: INFO, для дебага поднимаем до DEBUG только нужные пакеты.
Добавляем в logback-spring.xml:
<appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="FILE"/>
<queueSize>512</queueSize>
<discardingThreshold>0</discardingThreshold>
</appender>
<root level="INFO">
<appender-ref ref="ASYNC_FILE"/>
</root>
Логи пишутся в отдельном потоке и не блокируют бизнес-логику.
Для отправки в Logstash/Fluentd добавляем TCP-аппендер:
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>logstash.example.com:5000</destination>
<encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
</appender>
══════ Навигация ══════
Вакансии • Задачи • Собесы
#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍15🔥2👏2🥱1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁32💯4👍1😢1
Forwarded from Библиотека собеса по Java | вопросы с собеседований
JIT (Just-In-Time) компилятор — это компонент JVM, который
JIT компилирует только те части кода, которые
#core
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥1👏1
Roadmap для Java-разработчика: интеграция ИИ-агентов в Enterprise
ИИ-агенты — это не только область
Ваш путь внедрения ИИ:
— изучение принципов взаимодействия с
— интеграция агентских паттернов в существующие `JVM`-сервисы;
— создание систем с разделением ответственности между агентами;
— мониторинг и отладка автономных процессов.
Курс «Разработка ИИ-агентов» даст необходимые навыки для проектирования интеллектуальных надстроек над сложными системами.
Повысить квалификацию в ИИ
При регистрации до 19 января действует акция «3 в 1»: один курс покупаете, два получаете в подарок.
Дедлайн: 19 января.
ИИ-агенты — это не только область
Python. В корпоративной разработке на Java архитектура и надёжность агентов выходят на первый план.Ваш путь внедрения ИИ:
— изучение принципов взаимодействия с
LLM через API;
— интеграция агентских паттернов в существующие `JVM`-сервисы;
— создание систем с разделением ответственности между агентами;
— мониторинг и отладка автономных процессов.
Курс «Разработка ИИ-агентов» даст необходимые навыки для проектирования интеллектуальных надстроек над сложными системами.
Повысить квалификацию в ИИ
При регистрации до 19 января действует акция «3 в 1»: один курс покупаете, два получаете в подарок.
Дедлайн: 19 января.
😁1
Kafka транзакции не панацея, а узкоспециализированный инструмент.
🔹 Что гарантируют Kafka транзакции:
— Атомарную публикацию в несколько топиков (все сообщения видны или ни одно).
— Связывание read → process → write в одну операцию для консьюмеров-продюсеров.
🔹 Что НЕ гарантируют:
— Откат изменений во внешних системах (БД, API, email).
— Защиту от дубликатов, если downstream-сервисы не настроены правильно.
🔹 Два реальных сценария использования транзакций:
Отправка события обработки заказа и событие в audit-топик с временной меткой. Если сервис упадёт между отправками, то при повторе время не совпадёт — история будет некорректной.
Транзакция гарантирует, что оба сообщения либо станут видимы консьюмерам одновременно, либо ни одно из них не будет доставлено.
Если сервис упадёт после отправки сообщений, но до коммита оффсета, downstream-сервисы увидят дубликаты.
Транзакции связывают отправку и коммит в одну атомарную операцию.
Транзакции добавляют накладные расходы и подходят только для специфических кейсов.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤3🔥2👏1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁15👍3🔥1🤩1
Идемпотентность — это свойство операции, которую можно выполнить несколько раз, получая тот же результат, что и при однократном выполнении.
Простыми словами: повторный вызов не меняет состояние системы после первого успешного выполнения.
Классический пример — HTTP методы: GET, PUT, DELETE идемпотентны, POST — нет.
🔹 Ключевые моменты
▪️ Идемпотентная операция: setStatus(ACTIVE) — сколько раз ни вызови, статус будет ACTIVE.
▪️ Неидемпотентная операция: balance += 100 — каждый вызов увеличивает баланс.
▪️ Идемпотентность ≠ отсутствие побочных эффектов (это чистота функций).
▪️ Критична для распределённых систем: retry-механизмы, очереди сообщений, API.
▪️ Защищает от дублирующих запросов при сетевых сбоях.
🔹 Под капотом
В реальных системах идемпотентность достигается через:
→ Idempotency Key — клиент генерирует уникальный ключ и передаёт в запросе. Сервер проверяет: если операция с таким ключом уже выполнялась — возвращает закешированный результат.
→ Версионирование — оптимистичные блокировки через версии записей (JPA @Version).
→ Уникальные идентификаторы — вместо "создай заказ" отправляем "создай заказ с ID=xyz". Повторный запрос с тем же ID игнорируется.
→ Статус-машины — переходы между состояниями: если уже в целевом состоянии, ничего не делаем.
🔹 Подводные камни
— Idempotency key нужно хранить ограниченное время (обычно 24 часа).
— Нужна атомарность проверки и выполнения.
— Сложность при асинхронной обработке.
— Не все бизнес-операции можно сделать идемпотентными.
— Overhead на хранение и проверку ключей.
— REST API с критичными операциями (платежи, создание заказов).
— Kafka consumers — защита от повторной обработки при rebalance.
— Интеграция с внешними системами через retry.
— Scheduled jobs, которые могут запуститься дважды.
— Распределённые транзакции (Saga pattern).
— Webhook обработчики.
— Любые операции с денежными средствами.
— Внутренние CRUD операции без side effects.
— Операции чтения (они идемпотентны по умолчанию).
— Высоконагруженные операции, где overhead критичен.
— Простые внутренние методы без внешних вызовов.
🔧 Бонус-трюк: в Spring можно создать аннотацию @Idempotent и реализовать через AOP с использованием Redis для хранения idempotency keys. Получается декларативная идемпотентность на уровне методов.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥4❤1👏1
💻 Kafka транзакции в Spring Boot: от конфига до кода
Разберём практическую реализацию транзакций на конкретном примере.
1️⃣ Конфигурация продюсера
2️⃣ Конфигурация консьюмера
3️⃣ Добавляем TransactionManager
4️⃣ Используем @Transactional
⚠️ Важно: если в приложении есть и Kafka и JPA TransactionManager:
Вариант 1 — пометить как @Primary:
Вариант 2 — явно указать:
⚠️ В большинстве систем дедупликация и идемпотентность — более простое и эффективное решение.
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#Enterprise
Разберём практическую реализацию транзакций на конкретном примере.
propertiesspring.kafka.producer.properties.enable.idempotence=true
spring.kafka.producer.properties.transactional.id=order-service-${random.value}-
propertiesspring.kafka.consumer.isolation-level=read_committed
@Bean
public KafkaTransactionManager<String, Object> kafkaTransactionManager(
ProducerFactory<String, Object> producerFactory
) {
return new KafkaTransactionManager<>(producerFactory);
}
@Transactional
public void publishOrderResult(OrderRequest request) {
String orderId = UUID.randomUUID().toString();
OrderPlacedEvent event = new OrderPlacedEvent(
orderId,
request.email(),
request.productName()
);
kafkaTemplate.send("order-placed", orderId, event);
kafkaTemplate.send("order-audit", orderId, event);
// Обе отправки атомарны — либо обе успешны, либо обе откатятся
}
Вариант 1 — пометить как @Primary:
@Primary
@Bean
public KafkaTransactionManager<String, Object> kafkaTransactionManager(...) {...}
Вариант 2 — явно указать:
@Transactional("kafkaTransactionManager")
public void publishOrderResult(...) {...}══════ Навигация ══════
Вакансии • Задачи • Собесы
#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥3👏1
🔥 Field vs Constructor Injection: зомби-объекты в production
Казалось бы, избитая тема. Но копните глубже @Autowired — и обнаружите, что ваши объекты после new существуют в состоянии "клинической смерти".
Автор разбирает не "удобство тестов" (это мелочи), а фундаментальные проблемы: нарушение контракта конструктора, проблемы с JMM, хрупкость при AOT-компиляции для GraalVM, race conditions в мультипоточке.
Рекомендую прочитать, если хотите понять почему Spring Framework 6 окончательно выбрал constructor injection, а не просто "так все делают".
🔗 Читайте подробнее
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#coreJava
Казалось бы, избитая тема. Но копните глубже @Autowired — и обнаружите, что ваши объекты после new существуют в состоянии "клинической смерти".
Автор разбирает не "удобство тестов" (это мелочи), а фундаментальные проблемы: нарушение контракта конструктора, проблемы с JMM, хрупкость при AOT-компиляции для GraalVM, race conditions в мультипоточке.
Рекомендую прочитать, если хотите понять почему Spring Framework 6 окончательно выбрал constructor injection, а не просто "так все делают".
══════ Навигация ══════
Вакансии • Задачи • Собесы
#coreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥5👏2
Please open Telegram to view this post
VIEW IN TELEGRAM
😁18🤡11🔥2
Backend Engineer (Java/Kotlin) — от 600 до 3 500 $ — офис (Минск)
Middle Java-разработчик — 240 000 - 260 000₽ — удалёнка
Java Developer — от 5 000 $ — удалёнка
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥2👏1
«Этот манёвр будет стоить нам 51 год...»
— или 20% от вашего бюджета на самообразование. В Java-мире архитектурные паттерны и алгоритмы — это то, что отличает мидла от сеньора. Не ждите особого случая, забирайте базу прямо сейчас.
Успейте купить курсы Proglib Academy по старой цене до понедельника:
— Разработка ИИ-агентов
— Математика для разработки AI-моделей
— ML для старта в Data Science
— Математика для Data Science
— Специалист по ИИ
— Алгоритмы и структуры данных
— Программирование на Python
— Основы IT для непрограммистов
— Архитектуры и шаблоны проектирования
Взять по старой цене
⚠️ Цены вырастут 19 января
— или 20% от вашего бюджета на самообразование. В Java-мире архитектурные паттерны и алгоритмы — это то, что отличает мидла от сеньора. Не ждите особого случая, забирайте базу прямо сейчас.
Успейте купить курсы Proglib Academy по старой цене до понедельника:
— Разработка ИИ-агентов
— Математика для разработки AI-моделей
— ML для старта в Data Science
— Математика для Data Science
— Специалист по ИИ
— Алгоритмы и структуры данных
— Программирование на Python
— Основы IT для непрограммистов
— Архитектуры и шаблоны проектирования
Взять по старой цене
⚠️ Цены вырастут 19 января
Forwarded from Библиотека задач по Java | тесты, код, задания
Как лучше защититься от SQL инъекции?
Anonymous Quiz
7%
Использовать метод escapeSql() для экранирования пользовательского ввода
5%
Прятать SQL-запросы в отдельные классы и файлы
2%
Ограничить длину вводимых данных пользователем
79%
Использовать PreparedStatement с параметризованными запросами
7%
Посмотреть ответ
😁7👍3🔥3
Наш подписчик спрашивает:
Перешли на Java 21, Virtual Threads зашли отлично. Теперь смотрю на Structured Concurrency API (JEP 462, пока в preview).
У нас классика: один запрос → параллельно дергаем несколько микросервисов → агрегируем ответ. Structured Concurrency пока preview feature. Стоит ли уже переходить или рано?
P.S. Если хотите задать вопрос, заполните нашу гугл-форму. Это займет 5 минут.
#DevLife
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🤔2❤1🔥1
Please open Telegram to view this post
VIEW IN TELEGRAM
💯19😁11👍6❤🔥1