Масштабирование Java-приложений
Масштабируемость — это способность Java-приложения справляться с увеличением нагрузки (больше пользователей, данных или операций) без потери производительности и надежности. Экосистема Java с её мощными фреймворками и библиотеками предоставляет инструменты для построения масштабируемых систем.
Ключевые стратегии масштабирования Java-приложений
1) Модульная архитектура и микросервисы
Разделяйте монолит: разбивайте приложение на небольшие независимые модули или микросервисы. Каждый сервис можно разрабатывать, деплоить и масштабировать независимо.
🔹 Преимущества: масштабируемость отдельных компонентов, изоляция отказов, ускорение разработки.
2) Горизонтальное и вертикальное масштабирование
🔹 Горизонтальное масштабирование — добавление серверов/инстансов для распределения нагрузки (например, AWS ELB или Nginx).
🔹 Вертикальное масштабирование — увеличение ресурсов на одном сервере (CPU, RAM).
Пример: Развертывание нескольких stateless-сервисов на Spring Boot за балансировщиком, хранение сессий в Redis.
3) Оптимизация базы данных
🔹 Пул подключений — используйте HikariCP для эффективного управления соединениями.
🔹 Кэширование — внедряйте Redis или Ehcache для сокращения повторяющихся запросов.
🔹 Шардирование и репликация — делите данные между БД или используйте реплики для высокой доступности.
Пример на 2 фото
4) Асинхронная и событийно-ориентированная обработка
🔹 ExecutorService — управление фоновыми задачами через пулы потоков.
🔹 Очереди сообщений — Kafka или RabbitMQ для декуплинга логики и повышения пропускной способности.
🔹 Реактивное программирование — Project Reactor или RxJava для неблокирующих, событийных приложений.
Пример на 3 фото
5) Балансировка нагрузки
🔹 Распределение запросов — с помощью балансировщиков предотвращайте перегрузку одного инстанса.
Пример: Nginx или AWS ELB для маршрутизации API-запросов к нескольким backend-инстансам Java.
6) Надежность и устойчивость
🔹 Отказоустойчивость и избыточность — проектируйте систему с учетом отказов, применяйте авто-масштабирование и резервные ресурсы.
🔹 Мониторинг и алерты — используйте Prometheus, ELK Stack и др. для отслеживания метрик и раннего выявления проблем.
Чеклист лучших практик
> Проектируйте stateless-сервисы для простоты горизонтального масштабирования.
> Используйте API для взаимодействия между модулями/сервисами.
> Регулярно мониторьте и анализируйте производительность.
> Реализуйте безопасность на каждом уровне: авторизация, шифрование, сканирование уязвимостей.
> Проектируйте с учетом роста и изменений.
👉 Java Portal
Масштабируемость — это способность Java-приложения справляться с увеличением нагрузки (больше пользователей, данных или операций) без потери производительности и надежности. Экосистема Java с её мощными фреймворками и библиотеками предоставляет инструменты для построения масштабируемых систем.
Ключевые стратегии масштабирования Java-приложений
1) Модульная архитектура и микросервисы
Разделяйте монолит: разбивайте приложение на небольшие независимые модули или микросервисы. Каждый сервис можно разрабатывать, деплоить и масштабировать независимо.
2) Горизонтальное и вертикальное масштабирование
Пример: Развертывание нескольких stateless-сервисов на Spring Boot за балансировщиком, хранение сессий в Redis.
3) Оптимизация базы данных
Пример на 2 фото
4) Асинхронная и событийно-ориентированная обработка
Пример на 3 фото
5) Балансировка нагрузки
Пример: Nginx или AWS ELB для маршрутизации API-запросов к нескольким backend-инстансам Java.
6) Надежность и устойчивость
Чеклист лучших практик
> Проектируйте stateless-сервисы для простоты горизонтального масштабирования.
> Используйте API для взаимодействия между модулями/сервисами.
> Регулярно мониторьте и анализируйте производительность.
> Реализуйте безопасность на каждом уровне: авторизация, шифрование, сканирование уязвимостей.
> Проектируйте с учетом роста и изменений.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Универсальная обёртка для API-ответов
Дженерики позволяют возвращать типобезопасные и переиспользуемые форматы ответов. Вот как создать обобщённую обёртку
👉 Java Portal
Дженерики позволяют возвращать типобезопасные и переиспользуемые форматы ответов. Вот как создать обобщённую обёртку
ApiResponse<T>
для любого payload-а API.Please open Telegram to view this post
VIEW IN TELEGRAM
Разница между ассоциацией, агрегацией и композицией в Java
Определение
↳ Ассоциация: Общее отношение между двумя объектами
↳ Агрегация: Отношение «имеет», при котором дочерний объект может существовать независимо
↳ Композиция: Отношение «часть», при котором дочерний объект не может существовать без родительского
Тип
↳ Ассоциация: Слабо связанное отношение
↳ Агрегация: Ослабленная форма ассоциации (частный случай ассоциации)
↳ Композиция: Усиленная форма ассоциации
Зависимость
↳ Ассоциация: Объекты независимы
↳ Агрегация: Дочерний объект может пережить родительский
↳ Композиция: Жизненный цикл дочернего объекта зависит от родительского
Владение
↳ Ассоциация: Отсутствует владение
↳ Агрегация: Разделённое владение
↳ Композиция: Исключительное владение
Жизненный цикл
↳ Ассоциация: У обоих объектов собственный жизненный цикл
↳ Агрегация: Родитель и потомок могут иметь разные жизненные циклы
↳ Композиция: Жизненный цикл дочернего объекта строго привязан к родительскому
Пример из реальной жизни
↳ Ассоциация: Студент <—> Университет (могут существовать независимо)
↳ Агрегация: Кафедра <—> Университет (могут существовать раздельно)
↳ Композиция: Сердце <—> Человек (не может существовать без человека)
Пример в Java
↳ Ассоциация: Класс A содержит ссылку на класс B
↳ Агрегация: Класс School содержит список объектов Student
↳ Композиция: Класс House содержит объекты Room (при удалении House удаляются и Room)
👉 Java Portal
Определение
↳ Ассоциация: Общее отношение между двумя объектами
↳ Агрегация: Отношение «имеет», при котором дочерний объект может существовать независимо
↳ Композиция: Отношение «часть», при котором дочерний объект не может существовать без родительского
Тип
↳ Ассоциация: Слабо связанное отношение
↳ Агрегация: Ослабленная форма ассоциации (частный случай ассоциации)
↳ Композиция: Усиленная форма ассоциации
Зависимость
↳ Ассоциация: Объекты независимы
↳ Агрегация: Дочерний объект может пережить родительский
↳ Композиция: Жизненный цикл дочернего объекта зависит от родительского
Владение
↳ Ассоциация: Отсутствует владение
↳ Агрегация: Разделённое владение
↳ Композиция: Исключительное владение
Жизненный цикл
↳ Ассоциация: У обоих объектов собственный жизненный цикл
↳ Агрегация: Родитель и потомок могут иметь разные жизненные циклы
↳ Композиция: Жизненный цикл дочернего объекта строго привязан к родительскому
Пример из реальной жизни
↳ Ассоциация: Студент <—> Университет (могут существовать независимо)
↳ Агрегация: Кафедра <—> Университет (могут существовать раздельно)
↳ Композиция: Сердце <—> Человек (не может существовать без человека)
Пример в Java
↳ Ассоциация: Класс A содержит ссылку на класс B
↳ Агрегация: Класс School содержит список объектов Student
↳ Композиция: Класс House содержит объекты Room (при удалении House удаляются и Room)
Please open Telegram to view this post
VIEW IN TELEGRAM
Пример выше демонстрирует, как с помощью дженериков можно создать типобезопасный и переиспользуемый процессор данных, который работает с коллекциями объектов, в данном случае, с сотрудниками (Employee).
Основные моменты:
>
>
> В
Вывод программы:
👉 Java Portal
Основные моменты:
>
DataProcessor<T>
— обобщённый класс, хранящий список элементов типа T
и предоставляющий метод getMax
(...), который возвращает максимум по заданному компаратору.>
Employee
реализует Comparable<Employee>
и переопределяет метод compareTo, чтобы сравнивать сотрудников по зарплате.> В
main()
создаются объекты сотрудников и добавляются в DataProcessor<Employee>
, после чего находится сотрудник с максимальной зарплатой.Вывод программы:
Highest paid: Bob ($75000.0)
Please open Telegram to view this post
VIEW IN TELEGRAM
Защита вашего приложения с помощью Spring Security и OAuth2 Login.
Публичный доступ разрешён к
Полное руководство читайте здесь: тык
👉 Java Portal
Публичный доступ разрешён к
/
и /login
, все остальные эндпоинты требуют аутентификации.Полное руководство читайте здесь: тык
Please open Telegram to view this post
VIEW IN TELEGRAM
image_2025-06-22_08-35-57.png
2.3 MB
ReadWriteLock в Java
Этот механизм значительно повышает пропускную способность в приложениях с преобладанием операций чтения по сравнению с использованием обычного взаимного исключения (например,
Как работает
🔹 Read Lock (блокировка на чтение):
Несколько потоков могут одновременно получить блокировку на чтение, если ни один поток не владеет блокировкой на запись и ни один поток не ожидает записи. Это позволяет выполнять параллельные операции чтения, что эффективно для ресурсов, к которым часто обращаются на чтение и редко — на запись.
🔹 Write Lock (блокировка на запись):
Только один поток может получить блокировку на запись, и только если в данный момент нет активных читателей и писателей. Это обеспечивает исключительный доступ при модификации данных, предотвращая неконсистентность.
Java предоставляет стандартную реализацию интерфейса
Пример применения
Допустим, у вас есть общая структура данных, например, кэш или список, к которым обращаются несколько потоков:
🔹 Читатели: множество потоков часто читают данные.
🔹 Писатели: время от времени поток обновляет данные.
Используя
👉 Java Portal
ReadWriteLock
— это утилита для работы с параллелизмом в Java, которая позволяет нескольким потокам одновременно читать ресурс, но только одному потоку — записывать, и только в том случае, если никакие другие потоки в данный момент не читают и не пишут.Этот механизм значительно повышает пропускную способность в приложениях с преобладанием операций чтения по сравнению с использованием обычного взаимного исключения (например,
synchronized
или ReentrantLock
), где доступ к ресурсу может получить только один поток за раз.Как работает
ReadWriteLock
Несколько потоков могут одновременно получить блокировку на чтение, если ни один поток не владеет блокировкой на запись и ни один поток не ожидает записи. Это позволяет выполнять параллельные операции чтения, что эффективно для ресурсов, к которым часто обращаются на чтение и редко — на запись.
Только один поток может получить блокировку на запись, и только если в данный момент нет активных читателей и писателей. Это обеспечивает исключительный доступ при модификации данных, предотвращая неконсистентность.
Java предоставляет стандартную реализацию интерфейса
ReadWriteLock
в виде класса ReentrantReadWriteLock
.Пример применения
Допустим, у вас есть общая структура данных, например, кэш или список, к которым обращаются несколько потоков:
Используя
ReadWriteLock
, вы позволяете всем читателям одновременно обращаться к данным, но гарантируете, что при обновлении данных писатель будет иметь исключительный доступ. Это повышает производительность и обеспечивает потокобезопасность.Please open Telegram to view this post
VIEW IN TELEGRAM
Это шпаргалка по основным командам Linux, разбитая по категориям.
🔹 Файлы и навигация
🔹 Системная информация
🔹 Сетевые команды
🔹 Процессы
🔹 Архивация и сжатие
🔹 Права доступа
🔹 Другие команды
👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
Параллельная хеш-таблица с мелкозернистой блокировкой:
Потокобезопасная хеш-таблица с блокировками на уровне бакетов для минимизации конфликтов — подходит для высокопроизводительных систем, таких как базы данных или кеши.
👉 Java Portal
Потокобезопасная хеш-таблица с блокировками на уровне бакетов для минимизации конфликтов — подходит для высокопроизводительных систем, таких как базы данных или кеши.
Please open Telegram to view this post
VIEW IN TELEGRAM
Java Enums — Всё, что нужно знать
1.
• Это называется enum (сокращение от enumeration).
• Используется для задания фиксированного набора констант (например, состояния заказа, роли пользователя).
2.
• Бросает исключение, если строка некорректна.
• Используется при маппинге из БД, пользовательского ввода или JSON (например, парсинг статуса из запроса).
3.
• Возвращает имя enum-константы в точности как оно определено.
• Используется при логировании, сериализации и т. д. (например, отображение enum как строки в ответе).
4.
• Возвращает позицию (начиная с 0).
• Используется только если порядок важен (обычно избегается ради стабильности) — например, для ранжирования уровней.
5.
• Используется для итерации по всем константам.
• Удобно для UI-дропдаунов, фильтров, пакетной обработки.
6.
• Добавляет поведение к enum.
• Используется, если для каждой константы нужна логика (например, isHoliday() для Day).
7.
• Используется для хранения дополнительных данных с каждой константой (например, код из БД, описание).
8. Enum с абстрактным методом
• Называется поведенческим enum'ом.
• Используется для логики, подобной конечному автомату (например, стратегии на константу).
9.
• Высокопроизводительное множество для enum.
• Используйте вместо HashSet<Enum> (например, для фильтрации флагов или ролей).
10.
• Эффективная key-value структура, использующая enum в качестве ключа.
• Быстрее и легче, чем HashMap<Enum, X> (например, для меток или конфигураций по статусу).
11.
• Работает с enum'ами нативно.
• Используется для route-логики (например, обработки каждого статуса по-своему).
👉 Java Portal
1.
enum Status { PENDING, APPROVED, REJECTED }
→ Базовый Enum• Это называется enum (сокращение от enumeration).
• Используется для задания фиксированного набора констант (например, состояния заказа, роли пользователя).
2.
Status.valueOf("APPROVED")
→ Преобразование строки в Enum• Бросает исключение, если строка некорректна.
• Используется при маппинге из БД, пользовательского ввода или JSON (например, парсинг статуса из запроса).
3.
Status.APPROVED.name()
→ Получить имя как строку• Возвращает имя enum-константы в точности как оно определено.
• Используется при логировании, сериализации и т. д. (например, отображение enum как строки в ответе).
4.
Status.APPROVED.ordinal()
→ Получить индекс Enum• Возвращает позицию (начиная с 0).
• Используется только если порядок важен (обычно избегается ради стабильности) — например, для ранжирования уровней.
5.
for (Status s : Status.values())
→ Перебор значений Enum• Используется для итерации по всем константам.
• Удобно для UI-дропдаунов, фильтров, пакетной обработки.
6.
enum Day { MON, TUE; boolean isWeekend() { return false; } }
→ Enum с методами• Добавляет поведение к enum.
• Используется, если для каждой константы нужна логика (например, isHoliday() для Day).
7.
enum Type { BASIC("B"), PREMIUM("P"); private String code; ... }
→ Enum с полями• Используется для хранения дополнительных данных с каждой константой (например, код из БД, описание).
8. Enum с абстрактным методом
enum Mode {
ON { void act() { /* что-то делаем */ } },
OFF { void act() { /* ничего не делаем */ } };
abstract void act();
}
• Называется поведенческим enum'ом.
• Используется для логики, подобной конечному автомату (например, стратегии на константу).
9.
EnumSet.of(Status.APPROVED)
→ EnumSet• Высокопроизводительное множество для enum.
• Используйте вместо HashSet<Enum> (например, для фильтрации флагов или ролей).
10.
EnumMap<Status, String>
→ EnumMap• Эффективная key-value структура, использующая enum в качестве ключа.
• Быстрее и легче, чем HashMap<Enum, X> (например, для меток или конфигураций по статусу).
11.
switch(status)
→ Enum в операторе switch• Работает с enum'ами нативно.
• Используется для route-логики (например, обработки каждого статуса по-своему).
Please open Telegram to view this post
VIEW IN TELEGRAM
Что такое daemon-поток в Java?
Daemon-поток — это фоновый поток, который работает для поддержки пользовательских потоков. Примеры — сборщик мусора или системы мониторинга. Главное отличие: daemon-потоки не мешают завершению работы JVM. Как только все пользовательские (не-daemon) потоки завершатся, JVM завершится автоматически, даже если daemon-потоки ещё работают.
Как создаете daemon-поток?
🔹 Создаёте поток как обычно
🔹 Вызываете
🔹 Запускаете поток через
Как только основной (пользовательский) поток завершится — JVM выключится, даже если daemon-поток всё ещё активен.
Используйте daemon-потоки для фоновых сервисов, которые не должны блокировать завершение приложения. Всегда вызывайте
👉 Java Portal
Daemon-поток — это фоновый поток, который работает для поддержки пользовательских потоков. Примеры — сборщик мусора или системы мониторинга. Главное отличие: daemon-потоки не мешают завершению работы JVM. Как только все пользовательские (не-daemon) потоки завершатся, JVM завершится автоматически, даже если daemon-потоки ещё работают.
Как создаете daemon-поток?
setDaemon(true)
до запуска потокаstart()
Как только основной (пользовательский) поток завершится — JVM выключится, даже если daemon-поток всё ещё активен.
Используйте daemon-потоки для фоновых сервисов, которые не должны блокировать завершение приложения. Всегда вызывайте
setDaemon(true)
до запускаPlease open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Разные способы защиты API-эндпоинтов
→ API-ключи
Клиент отправляет ключ в заголовках или query-параметрах
👍 Просто реализуется
👎 Нет идентификации пользователя, легко утечь
→ OAuth2 (токены доступа)
Механизм авторизации через токены с областью доступа и сроком действия
👍 Тонкая настройка прав доступа, широко поддерживается
👎 Более сложная настройка
→ JWT (JSON Web Tokens)
Самодостаточный токен с наборами claims
👍 Без состояния (stateless), хорошо масштабируется
👎 Сложно отзывать, больше размер
→ Basic Auth
Отправка Base64(username:password) в заголовке
👍 Удобно для быстрого тестирования
👎 Никогда не используйте в продакшене
→ mTLS (взаимная TLS-аутентификация)
И клиент, и сервер проверяют сертификаты друг друга
👍 Высокий уровень доверия и шифрования
👎 Сложная инфраструктура и управление сертификатами
Для внутренних сервисов → mTLS + токены с коротким сроком жизни
Для публичных API → OAuth2 + scopes (области доступа)
Для тестирования/разработки → API-ключи или Basic Auth
👉 Java Portal
→ API-ключи
Клиент отправляет ключ в заголовках или query-параметрах
→ OAuth2 (токены доступа)
Механизм авторизации через токены с областью доступа и сроком действия
→ JWT (JSON Web Tokens)
Самодостаточный токен с наборами claims
→ Basic Auth
Отправка Base64(username:password) в заголовке
→ mTLS (взаимная TLS-аутентификация)
И клиент, и сервер проверяют сертификаты друг друга
Для внутренних сервисов → mTLS + токены с коротким сроком жизни
Для публичных API → OAuth2 + scopes (области доступа)
Для тестирования/разработки → API-ключи или Basic Auth
Please open Telegram to view this post
VIEW IN TELEGRAM
Ограничение частоты запросов в Spring Boot с помощью Bucket4j
Реализация rate limiting в REST API на Spring Boot с использованием Bucket4j для контроля частоты запросов на пользователя, что повышает масштабируемость API. Подходит для предотвращения злоупотреблений в продакшн-системах
• Импортируются классы из Bucket4j, Spring и Java SDK.
• Создаётся REST-контроллер с маппингом
• Для каждого пользователя создаётся бакет с лимитом 5 запросов в минуту. Если бакет позволяет — запрос проходит. Если нет — возвращается 429 статус.
• Заглушка для
👉 Java Portal
Реализация rate limiting в REST API на Spring Boot с использованием Bucket4j для контроля частоты запросов на пользователя, что повышает масштабируемость API. Подходит для предотвращения злоупотреблений в продакшн-системах
• Импортируются классы из Bucket4j, Spring и Java SDK.
• Создаётся REST-контроллер с маппингом
/api
• Для каждого пользователя создаётся бакет с лимитом 5 запросов в минуту. Если бакет позволяет — запрос проходит. Если нет — возвращается 429 статус.
• Заглушка для
HttpServletResponse
, нужна чтобы код можно было запускать без настоящего HTTP-сервера.Please open Telegram to view this post
VIEW IN TELEGRAM
Все ключевые слова Java в одном месте
Java содержит 53 зарезервированных ключевых слова, которые нельзя использовать как имена переменных, методов или классов — каждое из них выполняет определённую роль в языке.
Независимо от того, только ли ты начинаешь изучать Java или готовишься к собеседованию — знание этих ключевых слов обязательно
👉 Java Portal
Java содержит 53 зарезервированных ключевых слова, которые нельзя использовать как имена переменных, методов или классов — каждое из них выполняет определённую роль в языке.
Независимо от того, только ли ты начинаешь изучать Java или готовишься к собеседованию — знание этих ключевых слов обязательно
Please open Telegram to view this post
VIEW IN TELEGRAM
Прокачай производительность своего Java-приложения с помощью мощного кэширования.
Узнай, как интегрировать Spring Boot, Redis и Docker в этом практическом гайде.
Читать сейчас: тык😈
👉 Java Portal
Узнай, как интегрировать Spring Boot, Redis и Docker в этом практическом гайде.
Читать сейчас: тык
Please open Telegram to view this post
VIEW IN TELEGRAM
Sealed-классы и интерфейсы в Java
Они позволяют явно контролировать, какие классы могут расширять или реализовывать тип — делая иерархии безопаснее, легче в сопровождении и идеально подходящими для исчерпывающего pattern matching'а
Начиная с Java 17, были введены sealed-классы и sealed-интерфейсы как способ ограничить и контролировать иерархию наследования.
Как это работает?
🔹 Используй модификатор
🔹 Все разрешённые подтипы должны находиться в одном модуле или пакете и обязаны быть помечены как
Зачем использовать sealed-классы и интерфейсы?
👉 Более строгая инкапсуляция и контроль над публичным API
👉 Безопасный и предсказуемый код (отлично подходит для pattern matching в
👉 Защита от нежелательного наследования или реализации
👉 Java Portal
Они позволяют явно контролировать, какие классы могут расширять или реализовывать тип — делая иерархии безопаснее, легче в сопровождении и идеально подходящими для исчерпывающего pattern matching'а
Начиная с Java 17, были введены sealed-классы и sealed-интерфейсы как способ ограничить и контролировать иерархию наследования.
Как это работает?
sealed
и ключевое слово permits, чтобы явно указать разрешённые подклассы или реализации.final
, sealed или non-sealed
Зачем использовать sealed-классы и интерфейсы?
switch
)Please open Telegram to view this post
VIEW IN TELEGRAM
This media is not supported in your browser
VIEW IN TELEGRAM
Давайте разберёмся с Git Merge и Rebase
Git предоставляет два мощных инструмента для интеграции изменений из одной ветки (часто feature-ветки) в другую (обычно main):
Merge и Rebase
Оба инструмента решают одну задачу — объединение кода, но делают это по-разному.
✔️ Git Merge
Merge создаёт новый коммит, который фиксирует объединение двух веток.
В истории это видно как слияние двух независимых линий разработки в одной точке.
Шаги:
1. Переключись на целевую ветку (обычно main)
2. Выполни
Результаты:
🔸 Создаётся новый merge-коммит в целевой ветке с ссылками на родительские коммиты
🔸 История целевой ветки становится разветвлённой, отражая все слияния
🔸 Это более безопасный вариант для командной работы — история изменений сохраняется
✔️ Git Rebase
Rebase переписывает историю ветки (обычно feature-ветки), как будто коммиты были сделаны поверх другой ветки (например, main).
Получается более линейная история без merge-коммитов.
Шаги:
1. Переключись на ветку, которую хочешь ребейзнуть (например, feature)
2. Выполни
Результаты:
🔸 Коммиты из feature будут повторно применены на вершину main, создаются новые коммиты с теми же изменениями
🔸 Целевая ветка (main) при этом не изменяется
🔸 История feature-ветки становится линейной, но её история будет переписана
Примечания:
После успешного rebase, финальное merge в main часто выполняется как fast-forward, т.к. история выглядит непрерывной
Rebase изменяет ветку, на которой ты находишься, а не целевую ветку
Итог:
👉 Java Portal
Git предоставляет два мощных инструмента для интеграции изменений из одной ветки (часто feature-ветки) в другую (обычно main):
Merge и Rebase
Оба инструмента решают одну задачу — объединение кода, но делают это по-разному.
Merge создаёт новый коммит, который фиксирует объединение двух веток.
В истории это видно как слияние двух независимых линий разработки в одной точке.
Шаги:
1. Переключись на целевую ветку (обычно main)
2. Выполни
git merge <feature>
— укажи имя исходной веткиРезультаты:
Rebase переписывает историю ветки (обычно feature-ветки), как будто коммиты были сделаны поверх другой ветки (например, main).
Получается более линейная история без merge-коммитов.
Шаги:
1. Переключись на ветку, которую хочешь ребейзнуть (например, feature)
2. Выполни
git rebase <main>
Результаты:
Примечания:
После успешного rebase, финальное merge в main часто выполняется как fast-forward, т.к. история выглядит непрерывной
Rebase изменяет ветку, на которой ты находишься, а не целевую ветку
Итог:
merge
сохраняет историю как есть → хорошо для командной работыrebase
делает историю аккуратной → хорошо для чистоты, но требует осторожностиPlease open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Базовые приёмы экономии памяти в Java
1. Ленивая инициализация "тяжёлых" полей
– Используйте lazy initialization, чтобы откладывать создание объекта до момента, когда он действительно понадобится.
2. Избегайте анонимных внутренних классов в циклах
– Каждое такое использование создаёт объект внутреннего класса — это скрытая нагрузка на память.
3. Используйте статические фабричные методы
– Они позволяют экономить память за счёт повторного использования уже созданных экземпляров, вместо создания новых при каждом вызове.
4. Применяйте метод intern()
– Метод
Используя
5. Используйте паттерн Flyweight для повторяющихся неизменяемых данных
– Экономит память за счёт разделения общих экземпляров (используется, например, в
👉 Java Portal
1. Ленивая инициализация "тяжёлых" полей
– Используйте lazy initialization, чтобы откладывать создание объекта до момента, когда он действительно понадобится.
2. Избегайте анонимных внутренних классов в циклах
– Каждое такое использование создаёт объект внутреннего класса — это скрытая нагрузка на память.
3. Используйте статические фабричные методы
– Они позволяют экономить память за счёт повторного использования уже созданных экземпляров, вместо создания новых при каждом вызове.
4. Применяйте метод intern()
– Метод
intern()
класса String возвращает каноническое представление строки.Используя
intern()
, можно гарантировать, что одна и та же строка будет представлена в памяти в виде единственного объекта, даже если она создаётся многократно.String s1 = "hello";
String s2 = "hello".intern();
5. Используйте паттерн Flyweight для повторяющихся неизменяемых данных
– Экономит память за счёт разделения общих экземпляров (используется, например, в
Integer.valueOf()
, Boolean.TRUE
и т.п.).Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM