Настройка зависимостей
Добавьте зависимость spring-boot-starter-actuator
, а также включите конечную точку shutdown
в конфигурационном файле:
management:
endpoints:
web:
exposure:
include: shutdown
endpoint:
shutdown:
enabled: true
/actuator/shutdown
, чтобы запустить процесс завершения работы. Spring Boot сначала прекратит прием новых запросов, а затем завершит работу после завершения всех текущих запросов.Применимые сценарии Подходит для ситуаций, где требуется управление процессом завершения работы через HTTP-интерфейсы. Важно обеспечить безопасность (например, ограничение доступа).
server.shutdown=graceful
(Spring Boot 2.3+)Способ настройки
Включите элегантное завершение работы и установите время ожидания в файле конфигурации application.yml
:
server:
shutdown: graceful
spring:
lifecycle:
timeout-per-shutdown-phase: 30s
Поддержка веб-серверов
@PreDestroy
Регистрация Shutdown Hook
В методе main
используйте Runtime.getRuntime().addShutdownHook()
для регистрации хука, который выполняет логику освобождения ресурсов:
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
context.close();
System.out.println("Ресурсы освобождены.");
}));
Использование аннотации @PreDestroy
В методе завершения бина добавьте логику освобождения ресурсов:
@Component
public class ResourceCleanup {
@PreDestroy
public void cleanup() {
// Освобождение пула подключений к базе данных, пула потоков и т.д.
}
}
```------
kill
kill
:
SpringApplication application = new SpringApplication(Application.class);
application.addListeners(new ApplicationPidFileWriter("/path/to/app.pid"));
application.run();
cat /path/to/app.pid | xargs kill
(избегайте kill -9
) 47.ApplicationContext.close()
Запуск закрытия через пользовательский контроллер или задачу по расписанию:
@RestController
public class ShutdownController implements ApplicationContextAware {
private ApplicationContext context;
@PostMapping("/shutdown")
public void shutdown() {
((ConfigurableApplicationContext) context).close();
}
}
SpringApplication.exit()
Реализация остановки с помощью кода завершения:
int exitCode = SpringApplication.exit(context, () -> 0);
System.exit(exitCode);
@EventListener(ContextClosedEvent.class)
public void onShutdown() {
nacosDiscoveryService.deregister(); // Удаление сервиса
}
Закрытые классы (Sealed Classes)
sealed
и permits
для контроля структуры наследования.public abstract sealed class Shape permits Circle, Rectangle, Square { ... }
final
, non-sealed
или sealed
, что улучшает безопасность и поддерживаемость кода.Модульное соответствие (Pattern Matching)
instanceof
модульное соответствие: упрощение проверки типов и преобразования:if (obj instanceof String s) {
System.out.println(s.toUpperCase());
}
switch
паттерн матчинга (предварительная функциональность): поддерживает типовое соответствие и условия-гаранты:return switch (obj) {
case Integer i -> "int: " + i;
case String s && s.length() > 0 -> "строка: " + s;
default -> "неизвестно";
};
``` 3. **Текстовые блоки (Text Blocks)**:
- Упрощает запись многострочных строк, поддерживает автоматическое управление отступами и переносами строк:
java
Копировать
```
String json = """
{
"name": "Java",
"version": 17
}
""";
Записи (Records):
- Используется для определения неизменяемых данных классов, автоматически генерирует методы equals()
, hashCode()
и toString()
:
java
Копировать
record Person(String name, int age) { }
Улучшенные псевдослучайные генераторы (Enhanced Pseudo-Random Number Generators):
- Введен интерфейс RandomGenerator
и класс-фабрика, поддерживающий более гибкий выбор алгоритмов генерации случайных чисел:
java
Копировать
RandomGenerator generator = RandomGeneratorFactory.of("L128X256MixRandom").create();
Фабричные методы для коллекций: - Упрощает инициализацию коллекций, поддерживает быстрое создание неизменяемых коллекций: java Копировать
List<String> list = List.of("a", "b", "c");
Set<Integer> set = Set.of(1, 2, 3);
Улучшение API потоков (Stream API):
- Добавлены новые методы, такие как toList()
, takeWhile()
и dropWhile()
:
java
Копировать
List<Integer> четные_числа = Stream.of(2, 4, 6, 8).takeWhile(n -> n % 2 == 0).toList();
Внешние функции и API памяти (Incubator):
- Предоставляет безопасный доступ к внешней памяти и возможность вызова локального кода, заменяет JNI и sun.misc.Unsafe
. ### 3. Оптимизация производительности и безопасности
Улучшенные NullPointerException: - Информация об ошибке указывает конкретную переменную или вызов метода, который является null, что упрощает отладку: Копировать
java.lang.NullPointerException: Невозможно вызвать "String.length()" поскольку "str" равно null
Усиленная защита внутренних API JDK:
- По умолчанию запрещено использование рефлексии для доступа к внутренним API JDK (например, sun.misc
), что повышает безопасность.
Контекстно-зависимые фильтры десериализации:
- Разрешает динамическую конфигурацию фильтров десериализации, предотвращая атаки с использованием вредоносных данных.
Улучшения ZGC (Z Garbage Collector)
- Гарbage collector с низкими паузами, поддерживающий параллельную обработку потоков и оптимизирующий управление большим объемом памяти.
var
)
var list = new ArrayList<String>();
HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(10)).build();
Когда новые объекты не могут быть распределены в новом поколении из-за недостатка пространства, это приводит к минорной сборке мусора (Minor GC). Если после нескольких минорных сборок мусора объекты все еще остаются живыми и требуют перехода в старое поколение, но пространство в старом поколении недостаточно для их размещения, это приводит к полной сборке мусора (Full GC). Например, при высокой конкуренции и создании большого количества объектов за короткий промежуток времени, некоторые из которых имеют длительный срок жизни и постоянно переходят в старое поколение, может возникнуть недостаток пространства в старом поколении.
Постоянное поколение используется для хранения метаданных классов, а метаспейс является его заменителем. Когда загружается большое количество классов, например, при использовании динамических прокси для создания множества классов или при использовании некоторых фреймворков (например, Spring, Hibernate), которые генерируют множество классов динамически, это может привести к недостатку пространства в постоянном поколении или метаспейсе, что вызывает полную сборку мусора (Full GC).#### 3. Явное вызов System.gc()
Явное вызов метода System.gc()
в коде рекомендует JVM выполнить полную сборку мусора (Full GC). Однако JVM может не выполнить полную сборку мусора немедленно и будет решать, следует ли это делать, в соответствии со своими стратегиями.
Когда созданный объект занимает больше определенного порога по размеру, он сразу распределяется в старом поколении. Если часто создаются большие объекты, это может привести к недостатку пространства в старом поколении, что вызывает полную сборку мусора (Full GC).
Если объект выживает несколько раз в молодом поколении (Minor GC), он будет продвигаться в старое поколение. Если слишком много объектов продвигаются в старое поколение, что приводит к недостатку места в старом поколении, это может спровоцировать полную сборку мусора (Full GC).
Добавление параметров запуска JVM, таких как -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log
, позволяет выводить информацию о сборке мусора в указанный файл журнала. Анализ логов сборки мусора позволяет понять время каждого вызова сборки мусора, использование кучи до и после сборки мусора и т.д. Например, если часто возникают полные сборки мусора (Full GC), а объем памяти в старой генерации после Full GC не уменьшается значительно, это может указывать на наличие утечек памяти.### 2. Использование инструментов для мониторинга
Проверьте код на наличие явных вызовов System.gc()
, избегайте необязательных вызовов. Также проверьте код на наличие создания большого количества больших объектов и наличие утечек памяти, таких как незакрытые ресурсы (например, файлы, соединения с базами данных и т.д.).
На основе конкретной ситуации приложения, настройте размер кучи JVM, пропорции молодой и старой генерации и т.д. Например, если обнаружено, что недостаток места в старой генерации приводит к частым полным сборкам мусора (Full GC), можно увеличить объем памяти в старой генерации.## 5. Как выявить причины транзакционных мертвых琐锁 в базе данных
База данных может столкнуться с ситуацией, когда два или более транзакта во время выполнения конфликтуют из-за борьбы за ресурсы блокировки, что приводит к состоянию мертвого ожидания. Это состояние называется мертвым琐锁. Ниже приведены общие методы для выявления причин мертвых琐锁 в базе данных.
Базовые системы управления базами данных обычно записывают информацию о мертвых琐锁 в логи, что позволяет получить ключевые данные о времени возникновения, задействованных транзактах и блокировках.
error.log
). Также можно использовать команду SHOW ENGINE INNODB STATUS
для получения информации о состоянии движка InnoDB, которая включает подробную информацию о последнем мертвом琐锁.alert_SID.log
). Можно также использовать представления V$LOCKED_OBJECT
и V$SESSION
для получения информации о текущих заблокированных объектах и сессиях.В реальном времени мониторинг состояния блокировок в базе данных позволяет определить, какие транзакты удерживают блокировки и ожидают других блокировок, что помогает выявить корень проблемы мертвых琐锁.- MySQL: Можно использовать команду SHOW PROCESSLIST
, чтобы просмотреть информацию о текущих транзакциях и потоках. Для просмотра информации о захвате и ожидании блокировок используйте представления INFORMATION_SCHEMA.INNODB_LOCKS
и INFORMATION_SCHEMA.INNODB_LOCK_WAITS
.
V$LOCK
и V$SESSION
для запроса информации о захвате и ожидании блокировок. Для настройки отслеживания событий с целью обнаружения мёртвых琐锁,可以使用DBMS_SYSTEM.SET_EVENTS
。Мёртвые琐锁通常是由于不正确的事务执行顺序引起的。通过分析事务的执行顺序和锁的获取顺序,可以找到可能导致死锁的代码逻辑。
Анализируйте код приложения, чтобы проверить наличие неразумной логики управления транзакциями и использования блокировок.
Недостаточная производительность базы данных также может вызывать проблемы с мертвым замком. Оптимизация конфигурации базы данных и SQL-запросов может снизить конкуренцию за блокировки и уменьшить вероятность возникновения мертвых замков.
Spring Cloud предоставляет полный набор решений для микросервисов, охватывающий управление службами, конфигурацию, балансировку нагрузки, отказоустойчивость и многое другое.
Системы управления рисками
Системы соответствия и противодействия отмыванию денег (AML)
Системы аудита и внутреннего контроля
Стабильность микросервисов должна быть гарантирована на всем жизненном цикле — от проектирования до эксплуатации. Основные принципы заключаются в предотвращении сбоев, быстром обнаружении и автоматическом восстановлении. В рамках этих стратегий следует выбирать подходящие инструменты (например, Spring Cloud Alibaba, Istio service mesh) и постоянно оптимизировать архитектуру для создания высоконадежной распределенной системы.### 1. Механизмы отказоустойчивости и разрывов
В Kubernetes (K8s) процесс запуска pod проходит через несколько состояний, наиболее распространённые из которых следующие:1. Ожидание: Pod принят системой Kubernetes, но еще не распределен на узел или ожидает распределения ресурсов, загрузки образов контейнеров и т.д. 2. Создание контейнера: Kubernetes создает контейнеры внутри pod на узле, в это время происходит загрузка образов контейнеров, инициализация окружения контейнера и т.д. 3. Запущено: Pod распределено на узел и все контейнеры успешно созданы и работают. В этом состоянии приложения внутри pod работают нормально и могут предоставлять услуги внешним потребителям. 4. Успешно завершено: Все контейнеры внутри pod успешно завершили свою работу и вышли. Обычно это указывает на завершение задачи. В этом состоянии pod больше не будет автоматически перезапущен системой Kubernetes. 5. Неудача: Контейнеры внутри pod завершили работу с ошибкой, например, из-за ошибки в приложении внутри контейнера или ошибки команды запуска контейнера. В этом случае pod может быть перезапущен согласно политике перезапуска, или он может остаться в состоянии "ошибка" до вмешательства человека. 6. Неизвестно: Kubernetes не может точно определить состояние pod, обычно из-за проблем с коммуникацией с узлом или средой выполнения контейнера. В этом случае требуется дальнейшее расследование сети кластера, состояния узлов и т.д.## 11. Какие типы ресурсов есть в k8s? Типы ресурсов в Kubernetes (k8s) являются ключевыми компонентами управления и координации контейнеризированных приложений, охватывая такие аспекты, как развертывание приложений, сеть, хранение, конфигурация, безопасность и т.д. Ниже приведены основные типы ресурсов в Kubernetes и их назначение:
Экспонируются приложения, управляются потоки и сетевые политики.
Тип ресурса | Цель | Типичные сценарии |
---|---|---|
Service | Определяет точки доступа для группы Pod, обеспечивая балансировку нагрузки и стабильный IP/DNS. | Внутренняя коммуникация сервисов, экспонирование внешнего доступа (ClusterIP, NodePort, LoadBalancer). |
Ingress | Управляет маршрутизацией внешнего HTTP/HTTPS трафика к сервисам внутри кластера, поддерживает маршрутизацию по пути или домену. | Предоставление внешних web-сервисов, единое управление входящими запросами. |
Endpoint | Записывает IP и порты Pod, находящихся за Service, автоматически поддерживаемые Kubernetes. | Сценарии пользовательского открытия сервисов (например, интеграция с внешними сервисами). |
NetworkPolicy | Определяет правила сетевой коммуникации между Pod (разрешение/отказ от трафика). | Реализация сетевого разделения микросервисов (например, разрешение только для определённых пространств имен). |
Управление конфигурацией приложений и контролем доступа.
Тип ресурса | Цель | Типичные сценарии |
---|---|---|
ConfigMap | Хранение незащищенной конфигурационной информации (например, переменных окружения, файлов конфигурации). | Разделение конфигурации приложения (адрес базы данных, уровень логирования). |
ServiceAccount | Назначение идентификатора для Pod для доступа к API Kubernetes. | Управление правами доступа Pod к ресурсам кластера. |
Role | Определение правил доступа в пространстве имен (например, операции над Pod, Service). | Ограничение доступа разработчиков к определенным ресурсам в пространстве имен. |
RoleBinding | Привязка Role или ClusterRole к пользователю, группе или ServiceAccount. | Аутентификация ServiceAccount для выполнения определенных действий. |
ClusterRole | Определение правил доступа на уровне кластера (например, операции над узлами, PV). | Права администратора, управление ресурсами между пространствами имен. |
ClusterRoleBinding | Привязка ClusterRole к пользователю, группе или ServiceAccount. | Предоставление прав управления на уровне кластера. |
Динамическое изменение ресурсов для сопротивления изменениям нагрузки.
Тип ресурса | Цель | Типичные сценарии |
---|---|---|
HorizontalPodAutoscaler (HPA) | Автоматическое масштабирование количества экземпляров Pod на основе использования CPU/памяти или других пользовательских метрик. | Ответ на пиковые нагрузки, автоматическое масштабирование веб-сервисов. |
VerticalPodAutoscaler (VPA) | Автоматическое изменение запросов и ограничений ресурсов для Pod (необходимо использовать с осторожностью). | Оптимизация распределения ресурсов, предотвращение избыточной конфигурации. |
Расширение API Kubernetes с помощью CRD.
Тип ресурса | Цель | Типичные сценарии |
---|---|---|
CustomResourceDefinition (CRD) | Определение типов пользовательских ресурсов, расширение функциональности Kubernetes. | Реализация модели Operator (например, управление базами данных, промежуточного программного обеспечения). |
Тип ресурса | Цель |
---|---|
Event | Запись изменений состояния ресурсов в кластере и журнал действий (например, неудачное расписание Pod, ошибки загрузки образа). |
Node | Представляет рабочие узлы в кластере, содержит информацию о состоянии узла и ресурсах. |
Базовые типы данных хранят конкретные значения данных. Java предоставляет 8 базовых типов данных, вот их размер в байтах и диапазон значений.
Тип данных | Размер в байтах | Диапазон значений |
---|---|---|
byte | 1 байт | -128 до 127 |
short | 2 байта | -32768 до 32767 |
int | 4 байта | -2147483648 до 2147483647 |
------------ | --------------- | ------------------------------------------------------------------------------------------------------ |
long | 8 байт | -9223372036854775808 до 9223372036854775807 |
float | 4 байта | Приблизительно ±3.40282347E+38F (эффективное количество цифр около 6 - 7) |
double | 8 байт | Приблизительно ±1.79769313486231570E+308 (эффективное количество цифр около 15) |
char | 2 байта | '\u0000' до '\uffff' (то есть от 0 до 65535) |
boolean | Не указано | true или false |
Ссылочные типы данных хранят адреса объектов, а не сами объекты. Обычные ссылочные типы данных включают:
String
является встроенным классом Java, используемым для работы со строками.int[]
— это массив целых чисел, String[]
— это массив строк.
Размер памяти, занимаемый ссылочными типами данных, зависит от конкретного объекта и реализации виртуальной машины. Обычно ссылка сама по себе занимает 4 байта (в 32-битной виртуальной машине) или 8 байт (в 64-битной виртуальной машине).Реализация HashMap
основана на хэш-таблице, которая использует массив + связанный список + красно-черное дерево. До JDK 1.8 использовался массив + связанный список, а с JDK 1.8 введено использование красно-черного дерева для оптимизации.
HashMap
имеет внутри себя массив объектов типа Node
, где Node
— это статический вложенный класс, используемый для хранения пар ключ-значение и их хеш-значений. Этот массив называется корзиной (bucket), а каждый элемент массива можно рассматривать как отдельную корзину.
Когда несколько ключей вычисляются с помощью хеш-функции и получают одинаковое позиционное значение, возникает конфликт хеш-функции. До JDK 1.8 HashMap
использовал метод цепочек для решения конфликтов хеш-функции, то есть конфликтующие пары ключ-значение хранились в виде связного списка в одной корзине.
В JDK 1.8 была введена оптимизация с использованием красно-черного дерева. Когда длина связного списка достигает определенного порога (по умолчанию 8) и длина массива достигает 64, связный список преобразуется в красно-черное дерево для повышения эффективности поиска. Когда количество узлов в красно-черном дереве меньше или равно 6, дерево преобразуется обратно в связный список.
HashMap
в основном связан с двумя параметрами: емкостью (capacity) и коэффициентом заполнения (load factor).Емкость представляет собой длину массива в HashMap
. Изначальная емкость по умолчанию равна 16. При каждом расширении емкость удваивается.
Коэффициент заполнения — это число с плавающей запятой, по умолчанию равное 0.75. Он указывает, насколько полной должна быть HashMap
перед тем, как будет запущено расширение. Когда количество пар ключ-значение превышает произведение емкости на коэффициент заполнения, происходит запуск механизма расширения.
HashMap
создает новый массив, длина которого в два раза больше исходного.HashMap
является нитезависимым, в то время как ConcurrentHashMap
является нитезависимым. Ниже представлены конкретные объяснения:
HashMap
HashMap
, если происходит расширение, может возникнуть ситуация, когда связный список образует цикл, что приведет к появлению бесконечного цикла при прохождении по HashMap
.ConcurrentHashMap
Технология разделения блокировки (JDK 1.7)
ConcurrentHashMap
использует технологию разделения блокировки, которая делит всю хеш-таблицу на несколько сегментов (Segment), каждый из которых независимо блокируется.CAS + синхронизация (JDK 1.8 метод)
ConcurrentHashMap
использует метод CAS (Compare and Swap) вместе с синхронизацией, что позволяет избежать блокировок и повысить производительность. - В JDK 8 произошли оптимизации в ConcurrentHashMap
, где больше не используется метод разделения блоков на сегменты, а вместо этого используются операции CAS (Compare and Swap) и ключевое слово synchronized
для обеспечения безопасности потока.
synchronized
для блокировки узла в этом месте, после чего выполняется операция вставки.volatile
гарантируется получение последней версии данных, поэтому блокировка не требуется. Кроме того, ConcurrentHashMap
использует различные оптимизационные приемы, такие как использование длины массива, которая всегда является степенью двойки, и вычисление хеш-значений и индексов с помощью битовых операций, что повышает производительность вычислений.HashMap
может столкнуться с проблемами несогласованности данных и разрушения структуры при многопоточной работе, в то время как ConcurrentHashMap
использует различные механизмы для обеспечения безопасности потока и максимизации производительности параллельного доступа.OutOfMemoryError
.Функция: Каждый Java-метод создает стековый кадр, который используется для хранения локальных переменных, стека операндов, динамической связи, информации о выходе из метода и т. д. Вызовы и возвраты методов соответствуют операциям ввода и вывода стекового кадра в стеке виртуальной машины.
Аномалии: Если запрос потока на глубину стека превышает допустимую глубину стека виртуальной машины, будет выброшено исключение StackOverflowError
. Если стек виртуальной машины может динамически расширяться, но не удается получить достаточно памяти при расширении, будет выброшено исключение OutOfMemoryError
.#### Локальный стек (Native Method Stacks)
Функция: Аналогичен стеку виртуальной машины, но служит для работы с местными методами (методами, реализованными на языках, отличных от Java). Локальная стековая память предоставляет пространство для хранения данных, используемых локальными методами.
Исключительные ситуации: как и в случае с виртуальной стековой памятью, могут возникнуть исключения StackOverflowError
и OutOfMemoryError
.### 2. Общие области для всех потоков
new
, выделяются в куче.OutOfMemoryError
.OutOfMemoryError
.intern()
класса String
.OutOfMemoryError
.DirectByteBuffer
пакета NIO, что может повысить производительность операций ввода-вывода.OutOfMemoryError
.Алгоритмы сборки мусора в JVM предназначены для автоматического освобождения памяти, занятой объектами, которые больше не используются, обеспечивая эффективное использование памяти системы. Вот несколько распространенных алгоритмов сборки мусора:
Принцип работы: Алгоритм состоит из двух этапов — "маркировки" и "очистки".На этапе маркировки сборщик мусора начинает с корневых объектов (например, ссылок в стеке, статических переменных и т. д.) и проходит по всем живым объектам, помеча их как активные. На этапе сборки освобождается память, занятая объектами, которые не были помечены (то есть мусором).
Преимущества и недостатки: Преимущество заключается в простоте реализации; недостаток — образование большого количества фрагментов памяти, что со временем может привести к невозможности выделения непрерывной памяти для больших объектов, что в свою очередь может вызвать преждевременную активацию нового цикла сборки мусора.### 2. Копирующий алгоритм (Copying)
Принцип работы: Доступная память делится на две равные части по объему. В каждый момент времени используется только одна часть. Когда эта часть заполняется, все еще живые объекты копируются в другую часть, а затем очищается использованная память.
Преимущества и недостатки: Преимущество — простота реализации и высокая эффективность сборки мусора, отсутствие образования фрагментов памяти; недостаток — уменьшение доступной памяти на половину, что снижает эффективность использования памяти. Этот алгоритм часто используется для сборки мусора в молодой генерации, так как большинство объектов в молодой генерации имеют короткий срок жизни, и количество живых объектов невелико, что делает копирование относительно дешёвым.### 3. Маркер-упаковщик (Mark-Compact)
Принцип работы: Процесс маркировки аналогичен маркер-сборщику, где все живые объекты помечаются. Однако вместо очистки мусора все живые объекты перемещаются к одному концу, а затем освобождается память за пределами этого конца.
Преимущества и недостатки: Преимущество — решение проблемы фрагментации памяти, возникающей при работе с маркер-сборщиком, и избежание низкой эффективности использования памяти, характерной для копирующего алгоритма; недостаток — дополнительные затраты на перемещение объектов, что снижает общую эффективность. Этот алгоритм часто используется для сборки мусора в старой генерации, так как объекты в старой генерации имеют длительный срок жизни, и затраты на перемещение объектов могут быть приемлемыми.### 4. Генерационная коллекция (Generational Collection)
Принцип работы: Память разделяется на различные области в зависимости от срока жизни объектов, обычно на молодую и старую генерацию. В молодой генерации объекты имеют короткий срок жизни, поэтому используются копирующие алгоритмы для сборки мусора; в старой генерации объекты имеют длительный срок жизни, поэтому используются маркер-сборщик или маркер-упаковщик для сборки мусора.
Преимущества и недостатки: Преимущество — объединение преимуществ различных алгоритмов, выбор подходящего алгоритма сборки мусора в зависимости от характеристик объектов, что повышает эффективность сборки мусора; недостаток — необходимость разбиения и управления кучей памяти, что увеличивает сложность системы.### 5. Инкрементальная коллекция (Incremental Collection)
Принцип работы: В процессе сборки мусора весь процесс разделен на несколько маленьких шагов, при каждом шаге собирается только часть памяти. Между каждыми двумя маленькими шагами программа имеет возможность выполнить небольшой отрезок времени, что позволяет снизить влияние сборки мусора на программу, обеспечивая приближенную к реальному времени сборку мусора.
Преимущества и недостатки: Преимуществом является снижение времени простоя при сборке мусора; недостатком является увеличение общего времени сборки мусора, так как между каждым шагом сборки требуется сохранение и восстановление контекста.### 6. Алгоритм областей (Region-Based)
Различные алгоритмы сборки мусора имеют свои преимущества и недостатки. JVM выбирает наиболее подходящий алгоритм сборки мусора в зависимости от конкретной сценария использования и конфигурации системы, чтобы достичь наилучшей производительности и эффективности использования ресурсов.## 17. Какие основные типы движков хранения используются в MySQL?
INSERT
и SELECT
, операции UPDATE
и DELETE
не поддерживаются.По умолчанию уровень изоляции READ COMMITTED используется в InnoDB.В MySQL по умолчанию уровень изоляции транзакций для движка InnoDB установлен на уровне повторяемого чтения (REPEATABLE READ). Уровень изоляции повторяемого чтения гарантирует, что при выполнении одного и того же запроса несколько раз в рамках одной транзакции результат будет всегда одинаковым. То есть во время выполнения транзакции изменения данных другими транзакциями не влияют на результаты запросов внутри текущей транзакции.
Ниже представлен код, демонстрирующий эффект уровня изоляции повторяемого чтения:
-- Сессия 1
-- Начать транзакцию
START TRANSACTION;
-- Установить уровень изоляции на повторяемое чтение
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- Выполнить запрос данных
SELECT * FROM your_table WHERE id = 1;
-- Здесь можно выполнять другие действия, моделирующие процесс выполнения транзакции
-- Второй раз выполнить тот же запрос данных
SELECT * FROM your_table WHERE id = 1;
-- Подтвердить транзакцию
COMMIT;
```-- Сессия 2
-- В течение выполнения транзакции в сессии 1 можно попытаться изменить данные
UPDATE your_table SET column_name = 'новое_значение' WHERE id = 1;
В этом примере сессия 1 начинает транзакцию с уровнем изоляции повторяемого чтения и выполняет два одинаковых запроса. Даже если в сессии 2 данные были изменены, результат второго запроса в сессии 1 все еще совпадает с первым запросом, что демонстрирует характеристики уровня изоляции повторяемого чтения.
-- Создание обычного индекса при создании таблицы
CREATE TABLE example_table (
id INT,
name VARCHAR(50),
INDEX idx_name (name)
);
```-- Добавление обычного индекса после создания таблицы
ALTER TABLE example_table ADD INDEX idx_id (id);
-- Создание уникального индекса при создании таблицы
CREATE TABLE unique_table (
id INT,
email VARCHAR(100),
UNIQUE INDEX idx_email (email)
);
-- Добавление уникального индекса после создания таблицы
ALTER TABLE unique_table ADD UNIQUE INDEX idx_id (id);
-- Создание первичного ключа при создании таблицы
CREATE TABLE primary_table (
id INT PRIMARY KEY,
name VARCHAR(50)
);
-- Добавление первичного ключа после создания таблицы
ALTER TABLE primary_table ADD PRIMARY KEY (id);
-- Создание полноценного индекса при создании таблицы
CREATE TABLE fulltext_table (
id INT,
content TEXT,
FULLTEXT INDEX idx_content (content)
);
-- Добавление полноценного индекса после создания таблицы
ALTER TABLE fulltext_table ADD FULLTEXT INDEX idx_content (content);
-- Создание составного индекса при создании таблицы
CREATE TABLE composite_table (
id INT,
name VARCHAR(50),
age INT,
INDEX idx_name_age (name, age)
);
-- Добавление составного индекса после создания таблицы
ALTER TABLE composite_table ADD INDEX idx_id_name (id, name);
-- Создание пространственного индекса при создании таблицы
CREATE TABLE spatial_table (
id INT,
location GEOMETRY,
SPATIAL INDEX idx_location (location)
);
-- Добавление пространственного индекса после создания таблицы
ALTER TABLE spatial_table ADD SPATIAL INDEX idx_location (location);
``` - **Applications**: Suitable for scenarios requiring spatial queries, such as searching by geographic locations in mapping applications or analyzing spatial data in Geographic Information Systems (GIS). Different types of indexes are suitable for different scenarios, so it is important to choose the most appropriate type of index based on business requirements and characteristics of the data. An excessive number of indexes can increase storage and maintenance requirements for the database, so they should be used wisely.### 20. Как оптимизировать производительность SQL
### 1. Уровень проектирования базы данных
- Оптимальное проектирование структуры таблиц
- **Нормализация**: Соблюдение нормальных форм баз данных для минимизации избыточности данных, обеспечения согласованности и целостности данных. Например, в системе электронной коммерции товарная информация, заказы и данные пользователей могут храниться в отдельных таблицах, чтобы избежать повторного хранения информации.
- **Денормализация**: В некоторых случаях для повышения производительности запросов можно ввести некоторую избыточность данных. Например, при выполнении запросов отчетов можно хранить часто используемые связанные поля в одной таблице, чтобы уменьшить количество операций соединения таблиц.
- Выбор подходящих типов данных
- **Минимизация типов данных**: Выбор минимального типа данных в соответствии с реальными потребностями хранения данных, что позволяет снизить использование места на диске и повысить скорость запросов. Например, если требуется хранить возраст, лучше использовать TINYINT вместо INT. - **Избегание использования TEXT и BLOB типов данных**: Обработка этих типов данных занимает больше времени, поэтому если действительно требуется хранить большие текстовые или двоичные данные, можно рассмотреть возможность их хранения в файловой системе, а в базе данных хранить только пути к этим файлам.
### 2. Уровень оптимизации индексов
- Оптимальное создание индексов
- **Создание индексов на часто используемых полях**: Например, на полях, которые часто используются в условии WHERE или JOIN. Например, в таблице пользователей часто выполняются запросы по электронной почте пользователя, поэтому можно создать индекс на поле электронной почты.
- **Создание составных индексов**: Когда условия запроса часто включают несколько полей, следует создать составной индекс. Необходимо учитывать принципы левого префикса, например, если создано составное индексное поле (col1, col2, col3), то при условии, что запрос включает col1 или col1 и col2 или col1, col2 и col3, можно использовать этот индекс.
- **Избегайте избыточного количества индексов**: Избыток индексов увеличивает затраты на обслуживание базы данных, так как каждое действие вставки, обновления или удаления требует обновления индексов. Поэтому следует создавать индексы только для необходимых полей.
### 3. Оптимизация SQL-запросов
- Оптимизация запросов - Избегайте использования `SELECT *`: ограничьтесь теми полями, которые вам нужны, чтобы снизить объем передаваемых данных и нагрузку на базу данных. Например, если требуется получить только имя и электронную почту пользователя, не используйте `SELECT *`.
- **Разумное использование `WHERE`-предиката**: переместите условия фильтрации как можно ближе к началу запроса, чтобы снизить ненужные операции сканирования данных. Например, сначала отфильтруйте записи, соответствующие условиям, а затем выполните сортировку и группировку.
- **Оптимизация операций `JOIN`**: по возможности используйте `INNER JOIN` вместо `OUTER JOIN`, так как `INNER JOIN` обычно работает быстрее. Также убедитесь, что на ключевых полях `JOIN` есть индексы.
- **Избегайте использования подзапросов**: подзапросы обычно работают медленнее, чем `JOIN`-операции. По возможности преобразуйте подзапросы в `JOIN`-операции. Например:
```sql
-- Пример подзапроса
SELECT column1 FROM table1 WHERE column2 IN (SELECT column2 FROM table2);
-- Преобразование в JOIN-операцию
SELECT t1.column1 FROM table1 t1 JOIN table2 t2 ON t1.column2 = t2.column2;
Добавьте EXPLAIN
или EXPLAIN FORMAT=JSON
перед SQL-запросом, чтобы просмотреть путь выполнения запроса.
Пример:
EXPLAIN SELECT * FROM users WHERE name = 'Alice';
Поле | Описание |
---|---|
type |
Метод доступа к данным. Если значение ALL , это означает полное сканирование таблицы; если значение ref , range или index , это указывает на использование индекса. |
key |
Имя реально используемого индекса. Если key равно NULL , это означает, что индекс не используется. |
--- | |
rows |
Ожидаемое количество просматриваемых строк. Чем меньше строк, тем эффективнее запрос. |
Extra |
Дополнительная информация. Например, Using index указывает на использование покрывающего индекса, а Using where — на необходимость фильтрации данных после использования индекса. |
key
имеет значение: это означает использование индекса (например, key: idx_name
).type
не равно ALL
: если значение равно ref
, range
, index
и т.д., обычно это указывает на использование индекса.rows
имеет небольшое значение: если количество просматриваемых строк значительно меньше общего количества строк в таблице, возможно, индекс используется.Даже если индекс создан, следующие действия могут привести к тому, что индекс не будет использоваться:
SELECT * FROM users WHERE YEAR(create_time) = 2023; -- Индекс не используется
Оптимизация: замените на диапазонный запрос:
SELECT * FROM users WHERE create_time BETWEEN '2023-01-01' AND '2023-12-31';
SELECT * FROM users WHERE id = '100'; -- Если тип поля `id` — INT, то строка приведёт к тому, что индекс не будет использован
OR
для незадействованных индексами полей:SELECT * FROM users WHERE name = 'Alice' OR age = 20; -- Если поле `age` не индексировано, индекс не будет использован
Оптимизация: используйте UNION ALL
:
SELECT * FROM users WHERE name = 'Alice'
UNION ALL
SELECT * FROM users WHERE age = 20;
```## 23. Кэш- Avalanche, кэш- пробой и кэш- пробитие
### 1. Кэш- Avalanche
- **Определение**: Кэш- Avalanche — это ситуация, когда большое количество кэшированных данных одновременно истекает сроком годности, что приводит к тому, что большинство запросов сразу обращаются к базе данных, увеличивая нагрузку на неё и потенциально приводя к её отказу, что может повлиять на нормальную работу всего системы.
- **Причины**: Обычно это происходит из-за некорректной настройки срока годности кэшированных данных, например, если большое количество данных было закэшировано в одно и то же время и им был установлен одинаковый срок годности, то когда эти данные истекут сроком годности одновременно, это вызовет кэш- Avalanche.
- **Решение**:
- **Установка случайного срока годности**: При кэшировании данных установите случайный срок годности для каждого элемента, чтобы избежать истечения срока годности большого количества данных одновременно. Например, если срок годности кэша был установлен в 1 час, его можно изменить на случайное значение от 30 минут до 1,5 часов.
### 2. Использование кэш-кластера
- **Использование распределенного кэш-кластера**: При использовании распределенного кэш-кластера данные хранятся в нескольких узлах, что позволяет избежать концентрации всех данных в одном кэш-сервере. Даже если часть узлов выходит из строя, это не повлияет на работу всего кэша.- **Предварительная загрузка данных**: В момент запуска системы или во время простоя можно заранее загружать популярные данные в кэш, чтобы избежать ситуации, когда множество запросов одновременно обращаются к базе данных в пиковые часы.### 2. Проблема пробоя кэша
- **Определение**: Пробой кэша происходит, когда популярные данные внезапно исчезают из кэша (например, срок действия кэша истекает), и в этот момент множество параллельных запросов обращаются к этим данным. Эти запросы обходят кэш и сразу обращаются к базе данных, что может вызвать высокую нагрузку на базу данных.
- **Причины**: Основной причиной является неправильная настройка срока действия кэша для популярных данных или случайное удаление этих данных из кэша по какой-то причине. В этот момент множество параллельных запросов могут обращаться к этим данным.
- **Решение**
- **Установка вечного срока действия для популярных данных**: Для очень важных популярных данных можно установить вечный срок действия или использовать другие методы для ручного обновления кэша, чтобы гарантировать, что эти данные всегда будут доступны в кэше и не исчезнут из-за истечения срока действия.
- **Использование блокировки**: Когда данные в кэше истекают, можно использовать распределённую блокировку, чтобы гарантировать, что только один запрос сможет обратиться к базе данных и обновить кэш, а остальные запросы будут ждать, пока кэш не будет обновлен. Например, можно использовать команду `SETNX` в Redis для реализации распределённой блокировки.### 3. Проблема пробоя кэша
- **Определение**: Пробой кэша происходит, когда клиентский запрос обращается к данным, которые отсутствуют как в кэше, так и в базе данных. Это приводит к тому, что каждый запрос обходит кэш и сразу обращается к базе данных. Если таких запросов много, это может создать огромную нагрузку на базу данных и даже привести к её отказу.
- **Причины**: Обычно это связано с намеренной атакой, например, когда хакеры отправляют множество запросов с ключами, которые не существуют, или когда бизнес-логика не обеспечивает строгую проверку данных, что приводит к появлению запросов с несуществующими ключами.
- **Решение**
- **Блум-фильтр**: Использование блум-фильтра перед кэшем для проверки наличия данных. Блум-фильтр — это вероятностная структура данных, которая позволяет быстро проверять наличие элемента в множестве. Когда приходит запрос, сначала проверяется ключ с помощью блум-фильтра, и если ключ отсутствует, возвращается ответ без обращения к базе данных, что помогает избежать пробоя кэша.
- **Кэширование пустых значений**: Когда данные не найдены в базе данных, можно кэшировать пустое значение и установить короткий срок его действия. Таким образом, при следующих запросах пустое значение можно будет получить из кэша, не обращаясь к базе данных снова.
## 24 Различия HashSet, LinkedHashSet, TreeSet, EnumSet, CopyOnWriteArraySet, ConcurrentSkipListSet В Java различные реализации интерфейса `Set` отличаются по структуре данных, порядку сортировки, потокобезопасности, производительности и подходящим сценариям использования. Вот основные различия между **HashSet, LinkedHashSet, TreeSet, EnumSet, CopyOnWriteArraySet, ConcurrentSkipListSet**:
Пожалуйста, обратите внимание, что в данном тексте нет необходимости в переводе дополнительных слов или фраз, так как они уже представлены на русском языке. ### 1. Таблица сравнения ключевых особенностей
| Основные характеристики | HashSet | LinkedHashSet | TreeSet | EnumSet | CopyOnWriteArraySet | ConcurrentSkipListSet |
| ------------------------------------ | ------------------------------ | ------------------------------- | ----------------------------- | -------------------------- | ------------------------ | ------------------------ |
| **Основной тип данных** | Хеш-таблица (массив + связанный список / красно-черное дерево) | Хеш-таблица + двусвязный список | Красно-черное дерево | Битовый вектор или массив (специализированный для перечислений) | Копируемый массив (копирование при записи) | Скользящее дерево (skip list) |
| **Порядок сортировки** | Отсутствует (порядок вставки не важен) | Сохраняет порядок вставки | Природный порядок / Настроенная сортировка | Порядок перечисления (фиксированный порядок) | Сохраняет порядок вставки | Природный порядок / Настроенная сортировка |
| **Потокобезопасность** | Непотокобезопасен | Непотокобезопасен | Непотокобезопасен | Непотокобезопасен | Потокобезопасен (копирование при записи) | Потокобезопасен (безблокировка) |
| **Разрешение null** | Да (один) | Да (один) | Нет | Нет (значения перечислений не могут быть null) | Да (один) | Нет || **Уникальность элементов** | Обязательно уникальны | Обязательно уникальны | Обязательно уникальны | Обязательно уникальны (уникальность значений перечислений) | Обязательно уникальны | Обязательно уникальны |
| **Способ сортировки** | Отсутствует | Порядок вставки | Сравнимый/Компаратор | Порядок объявления перечисления | Порядок вставки | Сравнимый/Компаратор |
| **Поддержка сценариев параллелизма** | Нет | Нет | Нет | Нет | Сценарии чтения с небольшим количеством записей | Сценарии высокой параллелизации с упорядоченными операциями | Внимание: В таблице выше "null" относится к значению null, которое может быть добавлено в коллекцию. | **Сценарии применения** | Быстрое удаление дубликатов, проверка уникальности | Сохранение порядка вставки при удалении дубликатов | Сортировка элементов, запросы диапазона | Уникальное множество для перечислений | Нитезащищенный низко-конкурентный режим записи | Высоко-конкурентные операции с упорядоченным множеством |
### 2. Подробный анализ характеристик
#### 1. HashSet
- **Структура данных**: Основана на хеш-таблице (оптимизация с использованием красно-черного дерева начиная с JDK 8).
- **Упорядоченность**: Неупорядочено, порядок хранения элементов не зависит от порядка вставки (порядок прохода не определен).
- **Нитезащита**: Не нитезащищено, требуется ручная синхронизация в многонитевых средах.
- **Поддержка null**: Разрешено одно значение null (из-за уникальности ключей).
- **Производительность**: Среднее время выполнения операций вставки, удаления и поиска **O(1)** (в идеальных условиях), самая быстрая реализация множества Set.
- **Типичные сценарии**: Необходимость быстрого определения наличия элемента или удаления дубликатов (например, очистка массива от дубликатов, подсчет уникальных элементов).
#### 2. LinkedHashSet
- **Структура данных**: Хеш-таблица + двусвязный список (сохраняет порядок вставки). - **Упорядоченность**: Сохраняет порядок **вставки** (проход по элементам происходит в порядке вставки).
- **Нитезащита**: Не нитезащищено, основана на `HashSet`, дополнительно поддерживает список.
- **Поддержка null**: Разрешено одно значение `null` (как и в `HashSet`).
- **Производительность**: Время выполнения операций вставки, удаления и поиска **O(1)** (низкая стоимость поддержания списка, производительность близка к `HashSet`).
- **Типичные сценарии**: Необходимость сохранения порядка вставки при удалении дубликатов (например, стратегии кэширования, последовательность логирования).
#### 3. **TreeSet**
- **Структура данных**: Красно-черное дерево (балансированное двоичное дерево поиска).
- **Упорядоченность**: Элементы сортируются по **естественному порядку** (реализация `Comparable`) или **пользовательскому порядку** (передача `Comparator`).
- **Нитезащита**: Не нитезащищено, требуется синхронизация в многонитевых средах (например, `Collections.synchronizedSortedSet`).
- **Поддержка null**: Не разрешено `null` (вставка `null` приводит к `NullPointerException`).
- **Производительность**: Время выполнения операций вставки, удаления и поиска **O(log n)** (красно-черное дерево гарантирует баланс, лучше обычного двоичного дерева поиска).
- **Типичные сценарии**: Необходимость сортировки элементов или запросов диапазона (например, получение минимального значения, операции с подмножествами `subSet()`).
#### 4. **EnumSet** - **Структура данных**: Основана на битовом векторе для перечислений (высокая эффективность при малом количестве значений) или массиве.
- **Упорядоченность**: Строго следуют порядку **объявления перечислений** (фиксированный порядок, неизменяемый).
- **Нитезащита**: Не нитезащищено, но без изменений состояния (обычно используется в однопоточных или без изменений сценариях).
- **Поддержка null**: Не разрешено null (вставка null приводит к NullPointerException). - **Специфичность**: Может хранить только элементы одного **перечисления типа**, при создании необходимо указать перечисление.
- **Производительность**: Почти все операции имеют сложность **O(1)** (реализованы с помощью битовых операций, без конфликтов хэширования или затрат на деревья).
- **Типичные сценарии использования**: Эффективное управление наборами значений перечислений (например, проверка прав доступа, состояние флагов).
#### 5. **CopyOnWriteArraySet**
- **Структура данных**: Основана на `CopyOnWriteArrayList`, при записи массив копируется (механизм создания снимков).
- **Порядок вставки**: Сохраняет порядок вставки (как `LinkedHashSet`, но потокобезопасен).
- **Потокобезопасность**: Потокобезопасен (запись защищена блокировками, чтение не защищено, подходит для сценариев с **многими чтениями и редкими записями**).
- **Поддержка null**: Допускает один элемент `null` (как `HashSet`).
- **Производительность**: - Чтение **O(1)** (без блокировок, прямой доступ к массиву);
- Запись **O(n)** (копирование массива, производительность значительно снижается при параллельной записи).
- **Типичные сценарии использования**: в многопоточной среде, когда частота обновления коллекции низкая, но часто требуется чтение (например, регистрация прослушивания событий).
#### 6. **ConcurrentSkipListSet**
- **Структура данных**: использует пропускное дерево (Skip List, поддерживает эффективные операции над упорядоченными множествами).
- **Упорядоченность**: элементы упорядочены по **естественному порядку** или **пользовательскому порядку** (как `TreeSet`, но потокобезопасен).
- **Потокобезопасность**: потокобезопасен (основан на алгоритмах без блокировок и операциях CAS, поддерживает высокую конкурентность).
- **Поддержка null**: не допускает `null` (как `TreeSet`).
- Производительность:
- Время выполнения операций вставки, удаления и поиска имеет сложность **O(log n)** (уровневый индекс пропускного дерева оптимизирует производительность, превосходит конкурентную производительность красно-черных деревьев);
- В конкурентных сценариях производительность значительно превышает `TreeSet` (не требует глобальной блокировки).
- **Типичные сценарии использования**: упорядоченные множества в условиях высокой конкурентности (например, реальное время статистики сортировки, упорядоченные очереди в распределённых системах).
### 3.Ключевые различия
#### 1. **Упорядоченность и методы сортировки**
- **Несортированные**: `HashSet` (полностью неупорядоченное множество).
- **Порядок вставки**: `LinkedHashSet`, `CopyOnWriteArraySet` (хранят элементы в порядке вставки).
- **Фиксированный порядок**: `EnumSet` (упорядочено по объявленному перечислению, неизменяемое).
- **Пользовательский порядок**: `TreeSet`, `ConcurrentSkipListSet` (на основе компаратора или естественного порядка).
#### 2. **Потокобезопасность**
- **Не потокобезопасные**: `HashSet`, `LinkedHashSet`, `TreeSet`, `EnumSet` (требуют ручного синхронизации).
- Потокобезопасные:
- `CopyOnWriteArraySet` (механизм копирования при записи, подходит для низкой конкурентности записей);
- `ConcurrentSkipListSet` (алгоритмы без блокировок, подходит для высокой конкурентности упорядоченных операций).
#### 3. **Поддержка null элементов**
- **Разрешение null**: `HashSet`, `LinkedHashSet`, `CopyOnWriteArraySet` (каждый разрешает один `null`).
- **Запрет null**: `TreeSet`, `ConcurrentSkipListSet` (вызывает исключение при попытке вставить `null`); `EnumSet` (значения перечислений сами по себе не могут быть `null`).#### 4. **Сводка по применению**
| Требование | Рекомендованный класс | Причина |
| ----------- | --------------------- | ------- |
| Обычное удаление дубликатов и быстрый поиск | `HashSet` | Среднее время выполнения O(1), простота и эффективность |
| Сохранение порядка вставки | `LinkedHashSet` | Упорядочен и имеет производительность, близкую к `HashSet` |
| Сортировка элементов / запросы диапазона | `TreeSet` | Реализован с использованием красно-черного дерева, что обеспечивает упорядоченность, подходит для однопоточной сортировки |
| Специализированный для перечислений | `EnumSet` | Оптимизирован для перечислений, не поддерживает `null`, максимальная производительность |
| Нитезащищён и сохраняет порядок вставки | `CopyOnWriteArraySet` | Копирование при записи гарантирует нитезащиту, подходит для случаев с большим количеством чтений и малым количеством записей (например, мониторинг конфигураций) |
| Высокопроизводительные операции над упорядоченными множествами в многонитевых средах | `ConcurrentSkipListSet` | Реализован с использованием прыжкового списка, обеспечивает блокировку без потерь, превосходит производительность `TreeSet` в многонитевых средах |
### 4. Примеры кода: демонстрация ключевых различий
#### 1. Порядок вставки и сортировка
```java
// HashSet (неупорядоченный)
Set<String> hashSet = new HashSet<>();
hashSet.add("B");
hashSet.add("A");
System.out.println(hashSet); // Порядок вывода не определён (например, [A, B] или [B, A])
```// LinkedHashSet (сохраняет порядок вставки)
Set<String> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add("B");
linkedHashSet.add("A");
System.out.println(linkedHashSet); // Выводит [B, A] (в порядке вставки)
// TreeSet (естественнная сортировка)
Set<Integer> treeSet = new TreeSet<>();
treeSet.add(3);
treeSet.add(1);
System.out.println(treeSet); // Выводит [1, 3] (по возрастанию)
#### 2. Пример нитезащиты (CopyOnWriteArraySet)
```java
Set<String> threadSafeSet = new CopyOnWriteArraySet<>();
// Можно безопасно добавлять элементы в многонитевой среде (копирование при записи)
new Thread(() -> threadSafeSet.add("A")).start();
new Thread(() -> threadSafeSet.add("B")).start();
enum Color { RED, GREEN, BLUE } Set colorSet = EnumSet.of(Color.RED, Color.GREEN); colorSet.add(Color.BLUE); // Разрешено, значение перечисления // colorSet.
```markdown
### 5. Заключение
При выборе реализации класса `Set`, следует учитывать следующие ключевые моменты:
1. **Необходимость упорядоченности**: Для неупорядоченного множества выбирайте `HashSet`, для упорядоченного по порядку вставки — `LinkedHashSet`, для сортированного по пользовательскому критерию — `TreeSet` или `ConcurrentSkipListSet`, а для перечислений — `EnumSet`.
2. **Требования к потокобезопасности**: В однопоточной среде используйте непотокобезопасные классы (высокая производительность), в многопоточной — выбирайте `CopyOnWriteArraySet` (низкая конкуренция при записи) или `ConcurrentSkipListSet` (высокая конкуренция при упорядоченных операциях).
3. **Тип элементов**: Для перечислений используйте `EnumSet`, для пользовательских объектов переопределите методы `hashCode()` и `equals()` для обеспечения уникальности.
4. **Требования к производительности**: В обычных сценариях предпочтительно использовать `HashSet`/`LinkedHashSet`, для сортированных данных — `TreeSet`, а для высоконагруженных упорядоченных сценариев — `ConcurrentSkipListSet`.
Через понимание ключевых различий между реализациями можно эффективно использовать коллекцию `Set` в различных сценариях, избегая проблем производительности и ошибок проектирования.
```## 25. Реализация принципа паттерна Singleton и его ключевые элементы
Основной принцип реализации паттерна Singleton заключается в контроле процесса создания экземпляров класса, чтобы гарантировать наличие только одного экземпляра данного класса во всем приложении и предоставление глобальной точки доступа для получения этого экземпляра. Вот подробное описание принципа и способов его реализации:
### 1. Приватный конструктор:
Задайте конструктор класса как приватный, чтобы запретить внешнему коду создание экземпляров класса с помощью ключевого слова `new`. Это позволяет контролировать создание экземпляров только через методы самого класса.
### 2. Статическая переменная:
Определите статическую переменную внутри класса для хранения единственного экземпляра класса. Поскольку статические переменные принадлежат классу и существуют только один раз в течение всего жизненного цикла класса, они обеспечивают уникальность экземпляра. Например, `private static Singleton instance;`.
### 3. Общедоступный метод доступа:
Предоставьте общедоступный статический метод (обычно называемый `getInstance`), который используется для получения единственного экземпляра класса. Внутри этого метода используйте логические проверки для определения наличия экземпляра.Если экземпляр еще не создан, создайте новый и присвойте его статической переменной; если экземпляр уже существует, верните его. Например:
```java
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
Механизмы потокобезопасности: В многопоточной среде для обеспечения уникальности экземпляра необходимо применять механизмы потокобезопасности. Можно использовать ключевое слово synchronized
для синхронизации метода getInstance
, чтобы гарантировать, что одновременно только один поток может войти в метод для создания экземпляра.
Также можно использовать двойное проверочное замыкание (Double-Checked Locking, DCL), статические внутренние классы и другие способы для обеспечения потокобезопасного одиночки, они используют ключевое слово volatile
или механизм загрузки класса для избежания проблем в многопоточной среде.
Различные реализации паттерна одиночки (например, голодающий одиночка, ленивый одиночка, двойное проверочное замыкание, статические внутренние классы и т. д.) отличаются по деталям реализации и сценариям использования, но все они следуют вышеупомянутым основным принципам.
Linux предоставляет множество командной строки для мониторинга производительности системы и использования ресурсов.Ниже приведены некоторые часто используемые команды мониторинга и их типичные применения:
top
: Отображает текущее состояние системы в реальном времени, включая использование процессора, памяти и другие метрики.htop
: Улучшенная версия top
, которая предоставляет более удобный интерфейс и дополнительные возможности для мониторинга.ps
: Показывает информацию о запущенных процессах.pidstat
: Предоставляет детализированную статистику по каждому процессу, включая использование ЦПУ, памяти, ввода/вывода и сетевые данные.vmstat
: Отслеживает использование оперативной памяти, страницирование, процессорное время и другие параметры.iostat
: Анализирует производительность ввода/вывода устройств, показывая данные о чтении и записи.netstat
: Отображает текущую статистику сети, включая активные соединения, слушающие порты и таблицы маршрутизации.iftop
: Интерактивный инструмент для анализа сетевого трафика, который позволяет просматривать передачу данных между различными хостами.sar
: Сохраняет и отображает системные данные, такие как использование ЦПУ, памяти, ввода/вывода и сетевые данные.dstat
: Объединяет различные данные о производительности системы в одном месте, позволяя легко сравнивать различные метрики.free
: Показывает использование оперативной памяти и swap-памяти.df
: Отображает информацию о свободном пространстве на диске.uptime
: Показывает время работы системы и среднюю загрузку процессора.mpstat
: Анализирует производительность каждого процессора в системе.lsof
: Отображает открытые файлы и сокеты процессами.strace
: Отслеживает системные вызовы, выполняемые процессом, что полезно для диагностики проблем.tcpdump
: Анализирует сетевой трафик, записывая пакеты для дальнейшего анализа.ss
: Анализирует состояние TCP/IP соединений, предоставляя подробную информацию о сокетах.ipcs
: Показывает информацию о IPC (Inter-Process Communication) объектах, таких как shared memory, semaphores и message queues.ipcrm
: Удаляет IPC объекты.ipcs -s
: Показывает информацию о семафорах.ipcs -m
: Показывает информацию о совместно используемых памятьях.ipcs -q
: Показывает информацию о очередях сообщений.ipcs -a
: Показывает общую информацию обо всех IPC объектах.ipcmk
: Создает новые IPC объекты.ipcs -l
: Показывает информацию о лимитах IPC.ipcs -u
: Показывает информацию о использовании IPC.ipcs -p
: Показывает информацию о процессах, использующих IPC.ipcs -t
: Показывает информацию о времени жизни IPC объектов.ipcs -c
: Показывает информацию о создании IPC объектов.ipcs -r
: Показывает информацию о удалении IPC объектов.ipcs -x
: Показывает информацию о расширении IPC объектов.ipcs -z
: Показывает информацию о размерах IPC объектов.ipcs -v
: Показывает информацию о версиях IPC объектов.ipcs -w
: Показывает информацию о времени ожидания IPC объектов.ipcs -n
: Показывает информацию о номерах IPC объектов.ipcs -o
: Показывает информацию о владельцах IPC объектов.ipcs -e
: Показывает информацию о ошибках IPC объектов.ipcs -f
: Показывает информацию о файлах IPC объектов.ipcs -g
: Показывает информацию о группах IPC объектов.ipcs -h
: Показывает помощь по команде ipcs.ipcs -i
: Показывает информацию о информации IPC объектов.ipcs -j
: Показывает информацию о журналах IPC объектов.ipcs -k
: Показывает информацию о ключах IPC объектов.ipcs -l
: Показывает информацию о лимитах IPC объектов.ipcs -m
: Показывает информацию о совместно используемых памятьях IPC объектов.ipcs -n
: Показывает информацию о номерах IPC объектов.ipcs -o
: Показывает информацию о владельцах IPC объектов.ipcs -p
: Показывает информацию о процессах, использующих IPC объекты.ipcs -q
: Показывает информацию о очередях сообщений IPC объектов.ipcs -r
: Показывает информацию о удалении IPC объектов.ipcs -s
: Показывает информацию о семафорах IPC объектов.ipcs -t
: Показывает информацию о времени жизни IPC объектов.ipcs -u
: Показывает информацию о использовании IPC объектов.ipcs -v
: Показывает информацию о версиях IPC объектов.ipcs -w
: Показывает информацию о времени ожидания IPC объектов.ipcs -x
: Показывает информацию о расширении IPC объектов.ipcs -y
: Показывает информацию о размерах IPC объектов.ipcs -z
: Показывает информацию о размерах IPC объектов.ipcs -A
: Показывает общую информацию обо всех IPC объектах.ipcs -B
: Показывает информацию о блоках IPC объектов.ipcs -C
: Показывает информацию о конфигурациях IPC объектов.ipcs -D
: Показывает информацию о данных IPC объектов.ipcs -E
: Показывает информацию о ошибках IPC объектов.ipcs -F
: Показывает информацию о файлах IPC объектов.ipcs -G
: Показывает информацию о группах IPC объектов.ipcs -H
: Показывает информацию о хэшах IPC объектов.ipcs -I
: Показывает информацию о информации IPC объектов.ipcs -J
: Показывает информацию о журналах IPC объектов.ipcs -K
: Показывает информацию о ключах IPC объектов.ipcs -L
: Показывает информацию о лимитах IPC объектов.ipcs -M
: Показывает информацию о совместно используемых памятьях IPC объектов.ipcs -N
: Показывает информацию о номерах IPC объектов.ipcs -O
: Показывает информацию о владельцах IPC объектов.ipcs -P
: Показывает информацию о процессах, использующих IPC объекты.ipcs -Q
: Показывает информацию о очередях сообщений IPC объектов.ipcs -R
: Показывает информацию о удалении IPC объектов.ipcs -S
: Показывает информацию о семафорах IPC объектов.ipcs -T
: Показывает информацию о времени жизни IPC объектов.ipcs -U
: Показывает информацию о использовании IPC объектов.ipcs -V
: Показывает информацию о версиях IPC объектов.ipcs -W
: Показывает информацию о времени ожидания IPC объектов.ipcs -X
: Показывает информацию о расширении IPC объектов.ipcs -Y
: Показывает информацию о размерах IPC объектов.ipcs -Z
: Показывает информацию о размерах IPC объектов.ipcs -a
: Показывает общую информацию обо всех IPC объектах.ipcs -b
: Показывает информацию о блоках IPC объектов.ipcs -c
: Показывает информацию о конфигурациях IPC объектов.ipcs -d
: Показывает информацию о данных IPC объектов.ipcs -e
: Показывает информацию о ошибках IPC объектов.ipcs -f
: Показывает информацию о файлах IPC объектов.ipcs -g
: Показывает информацию о группах IPC объектов.ipcs -h
: Показывает помощь по команде ipcs.ipcs -i
: Показывает информацию о информации IPC объектов.ipcs -j
: Показывает информацию о журналах IPC объектов.ipcs -k
: Показывает информацию о ключах IPC объектов.ipcs -l
: Показывает информацию о лимитах IPC объектов.ipcs -m
: Показывает информацию о совместно используемых памятьях IPC объектов.ipcs -n
: Показывает информацию о номерах IPC объектов.ipcs -o
: Показывает информацию о владельцах IPC объектов.ipcs -p
: Показывает информацию о процессах, использующих IPC объекты.ipcs -q
: Показывает информацию о очередях сообщений IPC объектов.ipcs -r
: Показывает информацию о удалении IPC объектов.ipcs -s
: Показывает информацию о семафорах IPC объектов.ipcs -t
: Показывает информацию о времени жизни IPC объектов.ipcs -u
: Показывает информацию о использовании IPC объектов.ipcs -v
: Показывает информацию о версиях IPC объектов.ipcs -w
: Показывает информацию о времени ожидания IPC объектов.ipcs -x
: Показывает информацию о расширении IPC объектов.ipcs -y
: Показывает информацию о размерах IPC объектов.ipcs -z
: Показывает информацию о размерах IPC объектов.ipcs -A
: Показывает общую информацию обо всех IPC объектах.ipcs -B
: Показывает информацию о блоках IPC объектов.ipcs -C
: Показывает информацию о конфигурациях IPC объектов.ipcs -D
: Показывает информацию о данных IPC объектов.ipcs -E
: Показывает информацию о ошибках IPC объектов.ipcs -F
: Показывает информацию о файлах IPC объектов.ipcs -G
: Показывает информацию о группах IPC объектов.ipcs -H
: Показывает информацию о хэшах IPC объектов.ipcs -I
: Показ------top
Показывает текущее состояние процессов и использование ресурсов системы (CPU, память, нагрузка и т. д.) в реальном времени.
Клавиши: P
(сортировка по CPU), M
(сортировка по памяти), q
выход.htop
Улучшенная версия top
(требуется установка), поддерживает цветовое выделение, работу мыши и более интуитивное управление процессами.
Команда установки: sudo apt install htop
(Debian/Ubuntu) или sudo yum install htop
(CentOS/RHEL).vmstat
Отчет о виртуальной памяти, процессах, активности CPU и состоянии I/O.
Пример: vmstat 1
(обновление каждую секунду).uptime
Показывает время работы системы, количество текущих пользователей и среднюю нагрузку за последние 1, 5 и 15 минут.free
Просмотр использования памяти и разделов обмена.
Часто используемые опции: free -h
(в человекочитаемом формате).vmstat -s
Показывает подробные статистические данные о памяти.mpstat
Просмотр использования многоядерного CPU (требуется установка пакета sysstat
).
Пример: mpstat -P ALL 1
(показывает состояние всех ядер CPU каждую секунду).sar
Инструмент отчета о системной активности, который позволяет записывать и анализировать исторические данные о производительности.
Пример: sar -u 1 3
(выборка данных о использовании CPU каждую секунду, всего три выборки).iostat
**Мониторинг использования I/O дисков и активности CPU.
Пример: iostat -x 1
(показывает расширенные статистические данные, обновление каждую секунду).iotop
Просмотр процессов, использующих высокий уровень I/O (требуется установка).
Команда установки: sudo apt install iotop
или sudo yum install iotop
.df
Просмотр использования пространства на дисках.
Часто используемые опции: df -h
(в человекочитаемом формате).du
Подсчет использования диска для каталогов или файлов.
Пример: du -sh /путь/к/каталогу
(показывает общую размерность каталога).netstat
Отображает соединения сети, таблицу маршрутизации, статистику интерфейсов и т. д. (некоторые функции устарели, рекомендуется использовать ss
).
Пример: netstat -tulnp
(просмотр слушающих портов и процессов).ss
Альтернатива netstat
, более быстрая и эффективная.
Пример: ss -tunlp
(отображение TCP/UDP слушающих портов).iftop
В реальном времени отслеживает использование пропускной способности сети (сортирует по объему передачи, требуется установка).
Команда установки: sudo apt install iftop
или sudo yum install iftop
.nload
Отображает графики реального времени для сетевых интерфейсов (требуется установка).
Пример: nload eth0
.### 6. Наблюдение за процессамиps
Просмотр моментального снимка текущих процессов.
Пример: ps aux
или ps -ef
.pidstat
Наблюдение за использованием CPU, памяти и I/O процессами (входит в состав пакета sysstat
).
Пример: pidstat -d 1
(каждую секунду отображает статистику использования I/O процессами).lsof
Список открытых файлов и сетевых соединений процессами.
Пример: lsof -i :80
(просмотр процессов, использующих порт Yöntem: 80).dstat
Многофункциональный инструмент наблюдения, объединяет возможности vmstat
, iostat
, netstat
и т.д.
Пример: dstat -cmsdnl
(наблюдение за CPU, памятью, диском, сетью).glances
Кросс-платформенный инструмент наблюдения (требуется установка), поддерживает веб-интерфейс.
Команда установки: pip install glances
.tail -f /var/log/syslog
В реальном времени отслеживает обновления журнала (подходит для большинства журналов).journalctl
Просмотр и управление журналами systemd (подходит для систем, использующих systemd).
Пример: journalctl -f
(в реальном времени отслеживает журнал).lscpu
Просмотр архитектуры и информации о ядрах CPU.lsblk
Список информации о блочных устройствах (дисках, разделах).sensors
Отображение температуры оборудования (требуется установка lm-sensors
).### Заключениеuptime
, top
, htop
.mpstat
, pidstat
.free
, vmstat
.iostat
, iotop
.ss
, iftop
, nload
.
Выбирать подходящий инструмент в зависимости от конкретной ситуации, при необходимости использовать команды grep
, awk
и т.д. для фильтрации вывода данных.@Qualifier
, чтобы указать конкретный Bean по имени (byName).required
, значение которого по умолчанию равно true
. Это означает, что зависимость должна быть внедрена; если в контейнере нет подходящего Bean, будет выброшено исключение. Если установить значение этого атрибута в false
, то при отсутствии подходящего Bean в контейнере, объект будет установлен в null
.name
и type
. Атрибут name
используется для указания имени Bean, которое требуется внедрить, а атрибут type
— для указания типа Bean.### Пример кода
Ниже приведен пример кода, демонстрирующий использование этих аннотаций:import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
// Определение сервисного интерфейса
interface MyService {
void doSomething();
}
// Реализация сервисного интерфейса
@Component
class MyServiceImpl implements MyService {
@Override
public void doSomething() {
System.out.println("Выполняю задачу...");
}
}
// Использование @Autowired для внедрения зависимости
@Component
class AutowiredExample {
@Autowired
private MyService myService;
public void performTask() {
myService.doSomething();
}
}
// Использование @Resource для внедрения зависимости
@Component
class ResourceExample {
@Resource
private MyService myService;
public void performTask() {
myService.doSomething();
}
}
В приведенном выше коде класс AutowiredExample
использует аннотацию @Autowired
для внедрения зависимости типа MyService
, а класс ResourceExample
использует аннотацию @Resource
для внедрения зависимости типа MyService
.
@Autowired
является наиболее распространенным выбором. Если проект должен следовать стандартам Java, или если желательна лучшая переносимость кода, то @Resource
является более подходящим выбором.Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )