Java | Фишки и трюки
الذهاب إلى القناة على Telegram
Java: примеры кода, интересные фишки и полезные трюки Купить рекламу: https://telega.in/c/java_tips_and_tricks ✍️По всем вопросам: @Pascal4eg Менеджер по рекламе: @shmyzna
إظهار المزيد6 954
المشتركون
-724 ساعات
+117 أيام
+830 أيام
أرشيف المشاركات
6 953
☕️ Создание классов и объектов
В этом видео автор показывает, как в Java создавать собственные классы и объекты. Разбирается структура класса, определение полей и методов, а также процесс создания экземпляров через ключевое слово new. Это практическая основа объектно-ориентированного программирования, без которой невозможно двигаться дальше.🗣️Запомни: умение создавать классы и объекты — фундамент для понимания всей работы с ООП в Java. 🤩 Java Фишки и трюки || #Видео
6 953
🌊 JEP 458: Stream Gatherers в Java 22
Java 22 добавила Gatherers — расширение Stream API, которое позволяет собирать элементы не только привычными map/filter/reduce, а своими кастомными способами. Теперь поток можно «собирать» прямо в процессе, без костылей.
📦 Простая идея Gatherer
Stream.of(1, 2, 3, 4, 5)
.gather(Gatherers.windowFixed(2))
.forEach(System.out::println);
➡️ Элементы пакуются по 2 штуки.
Вывод:
[1, 2] [3, 4] [5]🔄 Sliding Window — скользящее окно
Stream.of(1, 2, 3, 4, 5)
.gather(Gatherers.windowSliding(3))
.forEach(System.out::println);
➡️ Формируются окна по 3 элемента с шагом в 1.
Вывод:
[1, 2, 3] [2, 3, 4] [3, 4, 5]🗂 Группировка по условию
Stream.of("a", "b", "x", "y", "c", "d")
.gather(Gatherers.groupUntil(s -> s.equals("x")))
.forEach(System.out::println);
➡️ Группа закрывается, когда встречается "x".
Вывод:
[a, b, x] [y, c, d]⚙️ Свой Gatherer
Gatherer<Integer, ?, Integer> sumPairs =
Gatherer.of(
() -> new int[1], // state
(state, e, down) -> {
state[0] += e;
if (state[0] >= 10) {
down.push(state[0]);
state[0] = 0;
}
return true;
},
(state, down) -> {}
);
Stream.of(3, 4, 5, 6, 7)
.gather(sumPairs)
.forEach(System.out::println);
➡️ Числа суммируются, пока не превысят 10, потом сбрасываются.
12
13
📊 Gatherers.fold — промежуточная агрегация
Stream.of(1, 2, 3, 4, 5)
.gather(Gatherers.fold(0, Integer::sum))
.forEach(System.out::println);
➡️ Видим все промежуточные суммы.
Вывод:
1 3 6 10 15⚖️ Gatherers 🆚 Collectors
Collectors работают в конце стрима (collect(...)). Gatherers же действуют прямо в процессе, шаг за шагом.➡️ Это позволяет писать stateful-преобразования, которые раньше выглядели громоздко. 🚀 Реальные применения
1. Буферизация при работе с большими потоками. 2. Batch-загрузки в БД. 3. Скользящие средние и метрики. 4. Stateful-пайплайны без ручного кода.➡️ Всё это теперь можно писать нативно в Stream API. 🔗 Комбинации
Stream.of(1, 2, 3, 4, 5, 6)
.gather(Gatherers.windowFixed(2))
.map(list -> list.stream().mapToInt(i -> i).sum())
.forEach(System.out::println);
➡️ Сначала разбиваем на пары, потом суммируем каждую.
Вывод:
3 7 11🗣️ Запомни: Gatherers в Java 22 выводят стримы на новый уровень. Они позволяют обрабатывать данные «на лету» и строить stateful-пайплайны, которые раньше были невозможны без костылей.
6 953
⌨️ Как вырасти до Мидла или Синьора в два раза быстрее?
👨💻Просто хорошо работать работу не достаточно. Ты делаешь то, что нужно компании, а не то, что повысит твой грейд
Лучший способ вырасти — это персональный план развития от Senior-инженера из БигТеха.
Вот как все работает:
1️⃣ Мок-интервью 1-на-1: Час реалистичного собеса с Senior-инженером из Иннотеха, Сбера или другого бигтеха
2️⃣ Честный фидбек: созвонимся и расскажем твои точки роста, оценим грейд и потенциальный уровень зарплаты
3️⃣Персональный план развития: не просто «учите алгосы», а роадмап с конкретными темами, который приведет тебя к желаемому грейду или офферу. Пример плана развития прикрепили к сообщению
Мы в ШОРТКАТ провели уже почти 1000 таких мок-интервью и получили оценку 4.9/5, поэтому знаем о чем говорим.
📈 Да, и все это за 900 рублей. Почему так дешево?
Мы хотим, чтобы у каждого была возможность проверить в деле наш сервис, а потом уже доверить нам свое развитие.
Переходи в нашего бота и забирай свой мок за 900 рублей → @shortcut_sh_bot Реклама.
О рекламодателе.
6 953
🚀 Spring Boot 3 + AOT компиляция — реальная производительность
Spring Boot 3 принёс AOT (Ahead-Of-Time) компиляцию. Теперь можно собирать приложение в нативный бинарь через GraalVM и запускать его почти мгновенно. Это не просто оптимизация — это новый уровень для микросервисов.
Разберём, что это даёт в реальных проектах 👇
⚡️ Запуск в миллисекунды
./mvnw -Pnative native:compile
./target/demo
➡️ Обычный Spring Boot на JVM стартует 2–5 секунд. AOT-бинарь поднимается за 30–50 мс. Это критично для serverless и микросервисов, где холодный старт решает.
📦 Минимальные Docker-образы
FROM ghcr.io/graalvm/native-image:latest as builder
WORKDIR /app
COPY . .
RUN ./mvnw -Pnative native:compile
FROM ubuntu:22.04
COPY --from=builder /app/target/demo /demo
CMD ["/demo"]
➡️ В Docker-контейнере не нужна JVM. Итоговый образ весит 30–50 MB вместо 300–400 MB.
🧠 Экономия памяти
JVM-приложение: 150–200 MB RAM
AOT-приложение: 20–40 MB RAM
➡️ GraalVM вырезает неиспользуемые классы, рефлексию и динамику. Сервер держит десятки сервисов вместо пары.
🔗 Поддержка Spring Boot Native
@SpringBootApplication
public class DemoApp {
public static void main(String[] args) {
SpringApplication.run(DemoApp.class, args);
}
}
➡️ Код не меняется. Но при сборке Spring генерирует hint'ы (reflect-config.json), чтобы GraalVM понял, какие классы реально нужны.
🧩 Работа с рефлексией и прокси
@TypeHint(types = {MyEntity.class}, access = AccessBits.ALL)
public class MyHints implements NativeConfiguration {}
➡️ В AOT режиме всё статично. Если библиотека лезет через Class.forName(), нужно явно подсказать GraalVM. Иначе приложение упадёт.
⚙️ Async, WebFlux, Security — всё работает
@GetMapping("/hello")
public Mono<String> hello() {
return Mono.just("Привет из AOT!");
}
➡️ Reactive-приложения и Spring Security совместимы. Но стоит проверить на совместимость сторонние библиотеки — они не всегда поддерживают AOT.
📊 JIT vs AOT: производительность под нагрузкой
🟢 JIT (обычная JVM) быстрее на долгих задачах, потому что оптимизирует байткод во время работы. 🟢 AOT быстрее стартует и экономнее в памяти, но чуть медленнее на горячем коде.➡️ Для микросервисов и API важнее быстрый старт и лёгкость. Для больших вычислений — JVM. 🔁 CI/CD и DevOps
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: ./mvnw -Pnative native:compile
- uses: actions/upload-artifact@v3
with:
name: demo-binary
path: target/demo
➡️ AOT встраивается в pipeline. Сборка дольше (5–10 минут), но итоговый бинарь быстрый и лёгкий.
🚨 Ограничения AOT
👍 Долгая компиляция (в разы медленнее, чем обычный mvn package). 👍 Динамические фреймворки (Hibernate proxies, некоторые reflection API) требуют ручных hint'ов. 👍 Не всегда легко дебажить — стек-трейсы короче.➡️ Но в продакшене эти минусы окупаются. 🗣️ Запомни: AOT в Spring Boot 3 — это не замена JVM, а выбор под задачу. Если важен холодный старт, размер образа и память — используй AOT. Если нужен гибкий код с динамикой и быстрые билды — оставляй JVM. Лучшие проекты совмещают оба подхода.
6 953
☕️Конструкторы класса
В этом видео автор объясняет, что такое конструкторы в Java и зачем они нужны. Пошагово показывается, как создавать конструкторы, передавать параметры при инициализации объектов и использовать перегрузку для разных вариантов создания экземпляров класса.🗣️Запомни: конструкторы упрощают инициализацию объектов и делают код более удобным и читаемым. 🤩 Java Фишки и трюки || #Видео
6 953
⌨️ Почему 1==1 это true, а 128==128 это false?
Integer a = 128;
Integer b = 128;
System.out.println(a == b); // false
Integer x = 1;
Integer y = 1;
System.out.println(x == y); // true
Это не просто волшебство! Это связано с целочисленным кэшированием в Java.
Для значений в диапазоне от -128 до 127 объекты типа Integer кэшируются, и ссылки на них одинаковы, а для значений за пределами этого диапазона создаются новые объекты, и ссылки на них будут разными. Так как используется оператор ==, то сравниваются ссылки на объекты.
#java #magic6 953
Нижний Новгород, намечается что-то классное
11 октября в вашем городе пройдет Сезон кода — ИТ-фест для тех, кто пишет код, держит прод и не боится сложных задач.
Соберем инженерное комьюнити города и выкатим осень на прод.
В программе фестиваля:
— доклады про надежность, масштабирование, перформанс, интеграции, инциденты и практики, которые реально работают;
— демо продуктов группы Т-Технологии — заглянем под капот инженерных решений и узнаем, как все устроено;
— карьерные консультации с HR-специалистами, которые расскажут, как расти в ИТ.
И, конечно, живое общение, активности от инженеров и тусовка с кавер-группой в конце дня.
Фест пройдет в культурном центре «Академия Маяк».
Успейте зарегистрироваться до 10 октября: https://vk.cc/cPyEgV?/erid=2W5zFGgDWhn
6 953
🚀 Project Loom: виртуальные потоки вместо тяжёлых тредов
Java всегда славилась многопоточкой, но классические треды прожорливы: на каждый создаётся отдельный системный поток. Loom это меняет — теперь у нас есть виртуальные потоки (virtual threads).
🧵 Старый способ — тяжёлые треды
Thread thread = new Thread(() -> {
System.out.println("Hello from thread!");
});
thread.start();
➡️ Потоки живут в ОС. Их немного, и каждый ест память и ресурсы.
⚡️ Новый способ — виртуальные потоки
Thread vThread = Thread.ofVirtual().start(() -> {
System.out.println("Hello from virtual thread!");
});
➡️ Здесь поток лёгкий. Java сама маппит тысячи виртуальных потоков на несколько системных.
🔄 Масштаб без боли
for (int i = 0; i < 1_000_000; i++) {
Thread.ofVirtual().start(() -> work());
}
➡️ Миллион потоков без OutOfMemoryError. На обычных тредах — краш.
⏸️ Блокировка без страха
Thread.ofVirtual().start(() -> {
Thread.sleep(1000); // блокируемся
System.out.println("Done!");
});
➡️ Виртуальные треды спокойно блокируются. JVM паркует их, освобождая ресурсы.
🌐 Асинхронщина без Future/CompletableFuture
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
executor.submit(() -> fetchFromApi());
executor.submit(() -> readFromDb());
}
➡️ Каждая задача — в своём виртуальном треде. Асинхронность пишется синхронно.
🔧 Работа с I/O
Files.lines(Path.of("data.txt"))
.forEach(line -> System.out.println(line));
➡️ Даже блокирующее I/O больше не страшно. В Loom оно «кажется» блокирующим, но реально не тормозит.
📊 Где использовать
🟢 сетевые сервисы (много коннектов); 🟢 микросервисы; 🟢 парсеры/скрейперы; 🟢 всё, где тысячи одновременных задач.🗣️ Запомни: Про «тредпулы и колбэки» скоро можно будет забыть.
6 953
🔍Тестовое собеседование с Java-разработчиком из МТС уже завтра
17 сентября(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика.
Как это будет:
📂 Илья Аров, старший разработчик в МТС, будет задавать реальные вопросы и задачи разработчику-добровольцу
📂 Илья будет комментировать каждый ответ респондента, чтобы дать понять чего от вас ожидает собеседующий на интервью
📂 В конце можно будет задать любой вопрос Илье
Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot
Реклама.
О рекламодателе.
6 953
⌨️ Приведение типов. Понижение и повышение типа
Java является строго типизированным языком программирования, а это означает, то что каждое выражение и каждая переменная имеет строго определенный тип уже на момент компиляции. Однако определен механизм приведения типов (casting) - способ преобразования значения переменной одного типа в значение другого типа.
В Java существуют несколько разновидностей приведения:
✔️ Тождественное (identity). Преобразование выражения любого типа к точно такому же типу всегда допустимо и происходит автоматически.
✔️ Расширение (повышение, upcasting) примитивного типа (widening primitive). Означает, что осуществляется переход от менее емкого типа к более ёмкому. Например, от типа
byte (длина 1 байт) к типу int (длина 4 байта). Такие преобразование безопасны в том смысле, что новый тип всегда гарантировано вмещает в себя все данные, которые хранились в старом типе и таким образом не происходит потери данных. Этот тип приведения всегда допустим и происходит автоматически.
✔️ Сужение (понижение, downcasting) примитивного типа (narrowing primitive). Означает, что переход осуществляется от более емкого типа к менее емкому. При таком преобразовании есть риск потерять данные. Например, если число типа int было больше 127, то при приведении его к byte значения битов старше восьмого будут потеряны. В Java такое преобразование должно совершаться явным образом, при этом все старшие биты, не умещающиеся в новом типе, просто отбрасываются - никакого округления или других действий для получения более корректного результата не производится.
✔️ Расширение объектного типа (widening reference). Означает неявное восходящее приведение типов или переход от более конкретного типа к менее конкретному, т.е. переход от потомка к предку. Разрешено всегда и происходит автоматически.
✔️ Сужение объектного типа (narrowing reference). Означает нисходящее приведение, то есть приведение от предка к потомку (подтипу). Возможно только если исходная переменная является подтипом приводимого типа. При несоответствии типов в момент выполнения выбрасывается исключение ClassCastException. Требует явного указания типа.
✔️ Преобразование к строке (to String). Любой тип может быть приведен к строке, т.е. к экземпляру класса String.
✔️ Запрещенные преобразования (forbidden). Не все приведения между произвольными типами допустимы. Например, к запрещенным преобразованиям относятся приведения от любого ссылочного типа к примитивному и наоборот (кроме преобразования к строке). Кроме того, невозможно привести друг к другу классы, находящиеся на разных ветвях дерева наследования и т.п.
При приведении ссылочных типов с самим объектом ничего не происходит, - меняется лишь тип ссылки, через которую происходит обращение к объекту.
Для проверки возможности приведения нужно воспользоваться оператором instanceof:
Parent parent = new Child();
if (parent instanceof Child) {
Child child = (Child) parent;
}
#java #casting #upcasting #downcasting6 953
Ты опытный Java-разработчик. Что дальше?
Дальше — искать новые пути развития и обмениваться знаниями. Это можно сделать на Joker — крупнейшей Java-конференции в России.
📍 17–18 октября, Санкт-Петербург
Тебя ждут хардкорные доклады о современных практиках Java-разработки, новых фичах Java, нюансах Spring, работе JVM под капотом, Kotlin и Scala, ORM и о базах данных. Еще там будут обсуждать архитектуру и backend, нагрузки и производительность, DevOps — выбирай, что ближе по духу.
Помимо докладов будут дискуссии со спикерами, зоны нетворкинга, а в конце первого дня — вечеринка!
Подробности и билеты — на сайте Joker.
С промокодом JF10 персональный билет стоит дешевле.
Реклама. ООО "ДЖУГ РУ ГРУП". ИНН 7801341446.
6 953
⌨️ Что такое default методы интрефейса?
Java 8 позволяет добавлять неабстрактные реализации методов в интерфейс, используя ключевое слово
default:
interface Example {
int process(int a);
default void show() {
System.out.println("default show()");
}
}
✔️Если класс реализует интерфейс, он может, но не обязан, реализовать методы по-умолчанию, уже реализованные в интерфейсе. Класс наследует реализацию по умолчанию.
✔️Если некий класс реализует несколько интерфейсов, которые имеют одинаковый метод по умолчанию, то класс должен реализовать метод с совпадающей сигнатурой самостоятельно. Ситуация аналогична, если один интерфейс имеет метод по умолчанию, а в другом этот же метод является абстрактным - никакой реализации по умолчанию классом не наследуется.
✔️Метод по умолчанию не может переопределить метод класса java.lang.Object.
✔️Помогают реализовывать интерфейсы без страха нарушить работу других классов.
✔️Позволяют избежать создания служебных классов, так как все необходимые методы могут быть представлены в самих интерфейсах.
✔️Дают свободу классам выбрать метод, который нужно переопределить.
✔️Одной из основных причин внедрения методов по умолчанию является возможность коллекций в Java 8 использовать лямбда-выражения.
Вызывать default метод интерфейса в реализующем этот интерфейс классе можно используя ключевое слово super вместе с именем интерфейса:
interface Paper {
default void show() {
System.out.println("default show()");
}
}
class Licence implements Paper {
public void show() {
Paper.super.show();
}
}6 953
☕️Функции в языке Java
В этом видео автор подробно разбирает, как создавать и использовать функции (методы) в Java. Пошагово объясняется, как объявлять методы, передавать параметры, возвращать значения и вызывать их из других частей программы.🤩 Java Фишки и трюки || #Видео
6 953
⚡️ Сотни курсов и книг по всем языкам программирования теперь доступны бесплатно:
🤩385 ГБ — Python
🤩229 ГБ — JS, HTML, CSS
🤩422 ГБ — C, C++, C#
🤩147 ГБ — Java, PHP
🤩202 ГБ — Rust, Golang
🤩352 ГБ — Flutter, Kotlin, Swift
🤩108 ГБ — ИИ, Machine Learning
🤩168 ГБ — DevOps, СисАдмин
🤩122 ГБ — Windows, Linux
🤩242 ГБ — БД (SQL и NoSQL)
🤩163 ГБ — QA-тестирование
🤩242 ГБ — ИБ, Хакинг
🤩189 ГБ — Разработка игр
🤩171 ГБ — Разработка ботов
🤩612 ГБ — Собеседования в IT
🤩3942 ГБ — Другие направления
База регулярно пополняется: Клик!
6 953
🏗 Java Module System (JPMS) — модульность приложения
С Java 9 появилась модульная система (JPMS), которая помогает разделять проект на независимые блоки и жёстко контролировать зависимости. Это шаг дальше от обычных JAR-файлов и классического classpath.
📦 Создание модуля через
module-info.java
module com.example.app {
requires com.example.service;
exports com.example.app.api;
}
➡️ Файл module-info.java лежит в корне src/com.example.app и описывает, какие модули нужны (requires) и какие пакеты доступны наружу (exports). Всё остальное скрыто.
🔒 Инкапсуляция пакетов
module com.example.service {
exports com.example.service.api;
// внутренние классы не экспортируются
}
➡️Код внутри модуля по умолчанию недоступен извне. Это защита от случайного использования «внутренних» API.
🔗 Транзитивные зависимости
module com.example.web {
requires transitive com.example.service;
}
➡️ Если модуль A требует B как transitive, то любой, кто подключает A, автоматически получает доступ к B.
🧩 Пример: приложение из трёх модулей
com.example.model → только данные com.example.service → бизнес-логика com.example.app → точка входа➡️ Модули явно описывают связи. Код не сможет обратиться к тому, что не экспортировано. ⚠️ Ошибка при неправильной зависимости
module com.example.model {
// ничего не экспортирует
}
module com.example.app {
requires com.example.model;
}
➡️ Компилятор выдаст ошибку: package ... is not visible. Нужно явно exports.
🚦 Сравнение с классическим classpath
👍 classpath: всё видно всем, легко словить «spaghetti» зависимостей. 👍 modules: строгие границы, меньше сюрпризов при рефакторинге.🔧 Совместимость и migration
🔴 Старые JAR можно подключать через automatic modules. 🔴 Постепенно можно переносить проект на полноценные модули.🗣️ Запомни: JPMS — это не только про разбиение проекта, но и про контроль связей. Модули делают систему чище, безопаснее и помогают строить большие приложения без хаоса зависимостей.
6 953
Роадмап подготовки к Java собеседованиям
Цель роадмапа – предоставить список тем и источников для быстрой подготовки к собеседованиям.
Темы:
– Java (архитектура jvm, gc, многопоточность)
– Spring (aop, transaction, cloud)
– SQL/NoSQL (acid, base, уровни изоляций, explain)
– Kafka/Docker/Kubernetes
– Паттерны проектирования, ООП, SOLID
– Алгоритмы и структуры данных
– Системный дизайн
Полная версия роадмапа со всеми темами и источниками лежит в канале @backend_interviewer
6 953
🛠 Memory-mapped Files — работа с файлами через ByteBuffer
Обычно мы читаем и пишем файлы через стандартные IO-потоки. Но у этого подхода есть потолок скорости. Memory-mapped files позволяют работать с файлами напрямую через память, минуя часть «лишних движений».
📂 Простое чтение через FileChannel
try (FileChannel channel = FileChannel.open(Path.of("data.txt"), StandardOpenOption.READ)) {
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());
}
}
➡️ Файл как будто целиком «подмонтирован» в память, а чтение идёт напрямую через ByteBuffer.
💾 Запись в файл
try (FileChannel channel = FileChannel.open(Path.of("out.txt"),
StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE)) {
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, 1024);
buffer.put("Hello world!".getBytes());
}
➡️ Любые изменения в буфере автоматически попадают в файл.
⚡ Работа с очень большими файлами
long size = 10L * 1024 * 1024 * 1024; // 10 GB
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, size);
➡️ Даже огромные файлы можно обрабатывать кусками, без полного чтения в память.
🔄 Двусторонний доступ
buffer.put(0, (byte) 'X');
System.out.println((char) buffer.get(0));
➡️ Одно и то же отображение позволяет и читать, и писать данные на месте.
🧱 Ограничения
Memory-mapped файлы зависят от ОС и архитектуры. Если закончилась виртуальная память — программа рухнет.➡️ Нужно аккуратно выбирать размер отображения и закрывать ресурсы. 🧵 Использование в многопоточке
// Несколько потоков читают один и тот же MappedByteBuffer
➡️ Общая память = быстрый обмен, но придётся синхронизировать доступ.
🗣️ Запомни:Memory-mapped files — это способ работать с файлами так, будто они часть оперативки. Он даёт скорость и гибкость, но требует аккуратного контроля памяти и синхронизации.6 953
Стойте! Если хотите шарить, или уже шарите в Java или Kotlin, то эти каналы однозначно для вас!
После их прочтения вы 100%
повысите свой уровень в несколько раз! Админ каналов Senior-разработчик, а значит ему можно доверять своё обучение:
1. Java Библиотека — Книги, статьи, фичи и советы. Сборная солянка для прогеров.
2. Kotlin Developer - самый топовый канал для котлин разработчика!
3. Книги для Java Программистов — Название говорит само за себя. Лучшие платные и бесплатные книги собраны в одном месте!
4. Java Guru — Хотите пройти собеседование и рубить по 300.000₽ в месяц? Всё возможно, но для этого надо прорешать не одну сотню задач и тестов — на этом канале как раз всё собрано.
5. Java News — А этот канал ежедневно вводит в курс дела и новостей любимого ЯП!
Подписывайтесь на все 5 каналов и станьте мега-программистом!
6 953
🔄 CompletableFuture + ExecutorService — сложные асинхронные цепочки
Java даёт мощный инструмент для работы с асинхронностью без сторонних библиотек —
CompletableFuture вместе с ExecutorService. С их помощью можно строить цепочки вычислений, обрабатывать ошибки и настраивать таймауты.
⚡️ Запуск асинхронной задачи
ExecutorService executor = Executors.newFixedThreadPool(4);
CompletableFuture<String> future =
CompletableFuture.supplyAsync(() -> {
sleep(500);
return "Результат";
}, executor);
System.out.println(future.join()); // блокируемся и получаем результат
executor.shutdown();
➡️ supplyAsync запускает задачу в отдельном потоке из пула.
🔗 Построение цепочек
CompletableFuture<Integer> chain =
CompletableFuture.supplyAsync(() -> 10)
.thenApply(x -> x * 2)
.thenApply(x -> x + 5);
System.out.println(chain.join()); // 25
➡️ Каждая операция обрабатывает результат предыдущей. Код становится декларативным.
🚦 Обработка ошибок
CompletableFuture<String> safe =
CompletableFuture.supplyAsync(() -> {
if (true) throw new RuntimeException("Ошибка");
return "OK";
}).exceptionally(ex -> "Fallback");
System.out.println(safe.join()); // Fallback
➡️ exceptionally позволяет задать запасной путь при сбое.
⏱️ Таймауты
CompletableFuture<String> future =
CompletableFuture.supplyAsync(() -> {
sleep(2000);
return "Долго";
});
String result = future.orTimeout(1, TimeUnit.SECONDS)
.exceptionally(ex -> "Таймаут")
.join();
System.out.println(result); // Таймаут
➡️ orTimeout прерывает выполнение, если задача не завершилась за указанное время.
🔀 Запуск нескольких задач
CompletableFuture<Integer> a = CompletableFuture.supplyAsync(() -> 1);
CompletableFuture<Integer> b = CompletableFuture.supplyAsync(() -> 2);
CompletableFuture<Integer> sum =
a.thenCombine(b, Integer::sum);
System.out.println(sum.join()); // 3
➡️ thenCombine позволяет объединять результаты из разных потоков.
🎭 AnyOf и AllOf
CompletableFuture<Object> any =
CompletableFuture.anyOf(a, b);
CompletableFuture<Void> all =
CompletableFuture.allOf(a, b);
➡️ anyOf завершится, когда готов хотя бы один, allOf — когда готовы все.
🧩 ExecutorService как фундамент
Важно передавать свой ExecutorService в supplyAsync и runAsync. Иначе будет использоваться общий ForkJoinPool, который не всегда предсказуем.🗣️ Запомни: CompletableFuture + ExecutorService дают асинхронность, цепочки и контроль ошибок прямо из коробки. Умение строить такие цепи позволяет писать быстрые и надёжные сервисы без Reactive или сторонних решений.
6 953
Гайд для маркетологов по эффективным онлайн-встречам
Как CMO, PR и digital-маркетологам повысить результативность брейнштормов, совещаний и планерок с командой с помощью онлайн-встреч?
Гайд МТС Линк: 37 страниц полезных материалов, чек-листов и кейсов для эффективных видеовстреч и совещаний.
✅ В гайде:
- Как создать постоянную ссылку на регулярные встречи с подрядчиками, командой или агентствами и подключаться в 2 клика;
- Как управлять встречей и завершить ее четкими договоренностями с ИИ-расшифровкой голоса в текст;
- Как проводить кастдевы, брейнштормы и формулировать гипотезы с помощью 15+ шаблонов в онлайн-досках МТС Линк;
- Как разом пригласить всех участников на синк таким образом, чтобы все пришли.
Бонус внутри: 5 способов не выгореть от бесконечных синков.
✨ Скачайте гайд бесплатно по ссылке
Скачать
#реклама 16+
mts-link.ru
О рекламодателе
متاح الآن! بحث تيليغرام 2025 — أهم رؤى العام 
