Пример рефакторинга предыдущего кода в unchecked-стиле:
В этом варианте SQLException перехватывается на границе инфраструктурного слоя и транслируется в DataAccessException — unchecked-исключение из Spring Framework. Доменное исключение UserNotFoundException также unchecked, так как отсутствие пользователя — это валидный бизнес-сценарий, который контроллер обрабатывает через глобальный обработчик исключений, преобразуя в HTTP 404.
Эволюция Spring Framework: от checked к unchecked
Spring Framework стал одним из первых major-фреймворков, систематически отказавшихся от checked-исключений. Философия Spring заключается в том, что большинство исключений в enterprise-приложениях — это фатальные сбои текущей операции, от которых невозможно восстановиться на месте.
Центральным элементом этой стратегии является иерархия DataAccessException. Spring перехватывает низкоуровневые checked-исключения (SQLException, HibernateException, JPAException) и транслирует их в структурированную иерархию unchecked-исключений: DataRetrievalFailureException, DataIntegrityViolationException, QueryTimeoutException и другие. Это достигается двумя целями: абстрагирование от конкретной технологии доступа к данным и признание того, что большинство ошибок базы данных фатальны для текущей транзакции.
Пример интеграции с Spring Data:
В этом коде отсутствуют объявления throws, несмотря на потенциальные сбои базы данных. Spring управляет транзакциями через @Transactional, и любое unchecked-исключение приводит к автоматическому откату.
Обработка ошибок централизована через @ControllerAdvice:
#Java #для_новичков #beginner #exception #checked #unchecked
// Кастомное unchecked-исключение для домена
public class UserNotFoundException extends RuntimeException {
private final String userId;
public UserNotFoundException(String userId) {
super("User not found: " + userId);
this.userId = userId;
}
}
// Репозиторий скрывает детали SQL, транслирует в доменное исключение
public User findById(String id) {
try {
Connection conn = dataSource.getConnection();
// ... выполнение запроса
} catch (SQLException e) {
throw new DataAccessException("Database error while loading user", e);
}
}
// Сервисный слой чист, без throws
public User getUser(String id) {
return userRepository.findById(id)
.orElseThrow(() -> new UserNotFoundException(id));
}
// Контроллер также чист, фокусируется на HTTP-логике
public UserDto getUserEndpoint(String id) {
User user = userService.getUser(id);
return userMapper.toDto(user);
}
В этом варианте SQLException перехватывается на границе инфраструктурного слоя и транслируется в DataAccessException — unchecked-исключение из Spring Framework. Доменное исключение UserNotFoundException также unchecked, так как отсутствие пользователя — это валидный бизнес-сценарий, который контроллер обрабатывает через глобальный обработчик исключений, преобразуя в HTTP 404.
Эволюция Spring Framework: от checked к unchecked
Spring Framework стал одним из первых major-фреймворков, систематически отказавшихся от checked-исключений. Философия Spring заключается в том, что большинство исключений в enterprise-приложениях — это фатальные сбои текущей операции, от которых невозможно восстановиться на месте.
Центральным элементом этой стратегии является иерархия DataAccessException. Spring перехватывает низкоуровневые checked-исключения (SQLException, HibernateException, JPAException) и транслирует их в структурированную иерархию unchecked-исключений: DataRetrievalFailureException, DataIntegrityViolationException, QueryTimeoutException и другие. Это достигается двумя целями: абстрагирование от конкретной технологии доступа к данным и признание того, что большинство ошибок базы данных фатальны для текущей транзакции.
Пример интеграции с Spring Data:
@Repository
public interface OrderRepository extends JpaRepository<Order, Long> {
// Метод объявлен без throws, но может выбросить unchecked исключения
Optional<Order> findByOrderNumber(String orderNumber);
}
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Transactional
public Order processOrder(String orderNumber) {
// Никаких try-catch для checked-исключений
Order order = orderRepository.findByOrderNumber(orderNumber)
.orElseThrow(() -> new OrderNotFoundException(orderNumber));
// При ошибке базы данных будет выброшено DataAccessException
// Транзакция откатится автоматически
return executeBusinessLogic(order);
}
}
В этом коде отсутствуют объявления throws, несмотря на потенциальные сбои базы данных. Spring управляет транзакциями через @Transactional, и любое unchecked-исключение приводит к автоматическому откату.
Обработка ошибок централизована через @ControllerAdvice:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(DataAccessException.class)
public ResponseEntity<ErrorResponse> handleDatabaseError(DataAccessException e) {
// Логирование, метрики, уведомление
return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE)
.body(new ErrorResponse("Database temporarily unavailable"));
}
@ExceptionHandler(OrderNotFoundException.class)
public ResponseEntity<ErrorResponse> handleNotFound(OrderNotFoundException e) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ErrorResponse(e.getMessage()));
}
}
#Java #для_новичков #beginner #exception #checked #unchecked
👍3
Этот подход разделяет бизнес-логику и обработку ошибок. Бизнес-код остается чистым и сфокусированным, в то время как обработка ошибок концентрируется в специализированных компонентах с полным контекстом HTTP-запроса.
Kotlin: полный отказ от checked-исключений
Kotlin пошел дальше, полностью устранив концепцию checked-исключений из языка. Все исключения в Kotlin по умолчанию unchecked, что соответствует философии минимизации шаблонного кода (boilerplate) и прагматичной разработки.
Это решение было обусловлено накопившимися проблемами checked-исключений в Java: многословностью, разрушением композиции в функциональном стиле, принуждением к плохим практикам (пустые catch-блоки, оборачивание в RuntimeException) и несовместимостью с лямбда-выражениями. Как отмечают разработчики Kotlin, за 25 лет checked-исключения в Java продемонстрировали столько же проблем, сколько решений, и ни один другой язык не принял эту модель .
В Kotlin код обработки ошибок выглядит естественно:
Ключевая концепция Kotlin — централизованная обработка I/O-ошибок. Вместо разбросанных по коду try-catch блоков для каждой сетевой операции, Kotlin предлагает выносить обработку на границу между бизнес-логикой и пользовательским интерфейсом. Это соответствует реальности enterprise-приложений, где сетевые сбои обрабатываются единообразно: retry с экспоненциальным backoff, fallback к кэшу или уведомление пользователя о временной недоступности сервиса.
Для взаимодействия с Java-кодом, использующим checked-исключения, Kotlin предоставляет аннотацию @Throws, которая генерирует соответствующие сигнатуры в байткоде для Java-вызывающих сторон. Однако внутри Kotlin- codebase эта информация не используется для статической проверки.
Фатальный удар: checked-исключения и Java 8 Streams
Введение лямбда-выражений и Stream API в Java 8 выявило фундаментальную несовместимость checked-исключений с функциональным программированием. Функциональные интерфейсы (Function<T,R>, Consumer<T>, Supplier<T>) не объявляют checked-исключений в своих абстрактных методах, что делает невозможным прямое использование методов, бросающих checked-исключения, в лямбдах.
Рассмотрим попытку использовать метод, объявляющий throws IOException, внутри Stream.map():
Разработчики вынуждены прибегать к обходным маневрам: оборачиванию исключений в RuntimeException внутри лямбды, созданию специальных функциональных интерфейсов с throws, или использованию библиотек вроде Vavr. Все эти решения уродливы и разрушают элегантность функционального стиля.
Пример оборачивания, который демонстрирует проблему:
Эта ситуация привела к тому, что комитет по развитию Java фактически признал checked-исключения тупиковой ветвью эволюции языка. Отсутствие поддержки checked-исключений в Stream API — это не oversight, а осознанное решение, демонстрирующее, что checked-исключения и современный Java несовместимы.
#Java #для_новичков #beginner #exception #checked #unchecked
Kotlin: полный отказ от checked-исключений
Kotlin пошел дальше, полностью устранив концепцию checked-исключений из языка. Все исключения в Kotlin по умолчанию unchecked, что соответствует философии минимизации шаблонного кода (boilerplate) и прагматичной разработки.
Это решение было обусловлено накопившимися проблемами checked-исключений в Java: многословностью, разрушением композиции в функциональном стиле, принуждением к плохим практикам (пустые catch-блоки, оборачивание в RuntimeException) и несовместимостью с лямбда-выражениями. Как отмечают разработчики Kotlin, за 25 лет checked-исключения в Java продемонстрировали столько же проблем, сколько решений, и ни один другой язык не принял эту модель .
В Kotlin код обработки ошибок выглядит естественно:
fun updateOrderQuantity(orderId: OrderId, quantity: Int) {
require(quantity > 0) { "Quantity must be positive" }
val order = loadOrder(orderId) // Может выбросить исключение, но не требует try-catch
order.quantity = quantity
storeOrder(order) // То же самое
}Ключевая концепция Kotlin — централизованная обработка I/O-ошибок. Вместо разбросанных по коду try-catch блоков для каждой сетевой операции, Kotlin предлагает выносить обработку на границу между бизнес-логикой и пользовательским интерфейсом. Это соответствует реальности enterprise-приложений, где сетевые сбои обрабатываются единообразно: retry с экспоненциальным backoff, fallback к кэшу или уведомление пользователя о временной недоступности сервиса.
Для взаимодействия с Java-кодом, использующим checked-исключения, Kotlin предоставляет аннотацию @Throws, которая генерирует соответствующие сигнатуры в байткоде для Java-вызывающих сторон. Однако внутри Kotlin- codebase эта информация не используется для статической проверки.
Фатальный удар: checked-исключения и Java 8 Streams
Введение лямбда-выражений и Stream API в Java 8 выявило фундаментальную несовместимость checked-исключений с функциональным программированием. Функциональные интерфейсы (Function<T,R>, Consumer<T>, Supplier<T>) не объявляют checked-исключений в своих абстрактных методах, что делает невозможным прямое использование методов, бросающих checked-исключения, в лямбдах.
Рассмотрим попытку использовать метод, объявляющий throws IOException, внутри Stream.map():
// Метод с checked-исключением
public String fetchDataFromUrl(String url) throws IOException {
return httpClient.fetch(url);
}
// Невозможно напрямую использовать в Stream
List<String> urls = List.of("http://api1.com", "http://api2.com");
List<String> data = urls.stream()
.map(this::fetchDataFromUrl) // Ошибка компиляции: IOException не обработано
.collect(Collectors.toList());
Разработчики вынуждены прибегать к обходным маневрам: оборачиванию исключений в RuntimeException внутри лямбды, созданию специальных функциональных интерфейсов с throws, или использованию библиотек вроде Vavr. Все эти решения уродливы и разрушают элегантность функционального стиля.
Пример оборачивания, который демонстрирует проблему:
List<String> data = urls.stream()
.map(url -> {
try {
return fetchDataFromUrl(url);
} catch (IOException e) {
throw new RuntimeException(e); // Уничтожение семантики checked-исключения
}
})
.collect(Collectors.toList());
Эта ситуация привела к тому, что комитет по развитию Java фактически признал checked-исключения тупиковой ветвью эволюции языка. Отсутствие поддержки checked-исключений в Stream API — это не oversight, а осознанное решение, демонстрирующее, что checked-исключения и современный Java несовместимы.
#Java #для_новичков #beginner #exception #checked #unchecked
👍4
Современные best practices: доминирование unchecked
Современные рекомендации по проектированию исключений в Java существенно эволюционировали. Если ранее считалось нормой делать все восстановимые сбои checked, то теперь преобладает подход "unchecked by default" с несколькими четкими критериями для исключений.
Используйте checked-исключения только когда:
- Восстановление возможно и вероятно на месте вызова. Пример: повторная попытка при временном сбое сети с backoff, запрос альтернативного ввода от пользователя.
- Исключение является частью доменной модели и требует явного внимания клиента. Пример: бизнес-исключение InsufficientFundsException в финансовой системе, где вызывающий код должен явно обработать сценарий недостаточности средств.
- API предназначен для широкого использования внешними клиентами, и пропуск исключения приведет к катастрофическим последствиям.
Во всех остальных случаях используйте unchecked-исключения:
- Программные ошибки (null-аргументы, выход за границы, нарушение инвариантов).
- Фатальные сбои внешних систем (база данных недоступна, сетевой таймаут), где восстановление требует транзакционной логики на более высоком уровне.
- Сценарии, где исключение транслируется через несколько слоев абстракции перед обработкой.
- Код, интегрирующийся с функциональными API (Streams, CompletableFuture, Optional).
Пример проектирования современного API:
PaymentReversalRequiredException — checked, потому что требует немедленного действия: отката платежа, уведомления бухгалтерии, возможно, ручного вмешательства. Это редкий, но критичный бизнес-сценарий.
PaymentProcessingException — unchecked, так как ошибки процессинга (таймаут, недоступность шлюза) фатальны для текущей операции и обрабатываются централизованно через retry-механизм или circuit breaker.
InvalidPaymentRequestException — unchecked, так как передача невалидных данных — это ошибка вызывающего кода, которая должна быть исправлена до деплоя.
#Java #для_новичков #beginner #exception #checked #unchecked
Современные рекомендации по проектированию исключений в Java существенно эволюционировали. Если ранее считалось нормой делать все восстановимые сбои checked, то теперь преобладает подход "unchecked by default" с несколькими четкими критериями для исключений.
Используйте checked-исключения только когда:
- Восстановление возможно и вероятно на месте вызова. Пример: повторная попытка при временном сбое сети с backoff, запрос альтернативного ввода от пользователя.
- Исключение является частью доменной модели и требует явного внимания клиента. Пример: бизнес-исключение InsufficientFundsException в финансовой системе, где вызывающий код должен явно обработать сценарий недостаточности средств.
- API предназначен для широкого использования внешними клиентами, и пропуск исключения приведет к катастрофическим последствиям.
Во всех остальных случаях используйте unchecked-исключения:
- Программные ошибки (null-аргументы, выход за границы, нарушение инвариантов).
- Фатальные сбои внешних систем (база данных недоступна, сетевой таймаут), где восстановление требует транзакционной логики на более высоком уровне.
- Сценарии, где исключение транслируется через несколько слоев абстракции перед обработкой.
- Код, интегрирующийся с функциональными API (Streams, CompletableFuture, Optional).
Пример проектирования современного API:
// Checked-исключение для редкого, но критичного сценария восстановления
public class PaymentReversalRequiredException extends Exception {
private final Payment originalPayment;
private final String reasonCode;
public PaymentReversalRequiredException(Payment payment, String reasonCode, String message) {
super(message);
this.originalPayment = payment;
this.reasonCode = reasonCode;
}
// Методы доступа для логики восстановления
public Payment getOriginalPayment() { return originalPayment; }
public String getReasonCode() { return reasonCode; }
}
// Unchecked-исключения для всех остальных сценариев
public class PaymentProcessingException extends RuntimeException {
private final String transactionId;
public PaymentProcessingException(String transactionId, String message, Throwable cause) {
super(message, cause);
this.transactionId = transactionId;
}
}
public class InvalidPaymentRequestException extends IllegalArgumentException {
private final String fieldName;
public InvalidPaymentRequestException(String fieldName, Object value) {
super(String.format("Invalid value for field %s: %s", fieldName, value));
this.fieldName = fieldName;
}
}
PaymentReversalRequiredException — checked, потому что требует немедленного действия: отката платежа, уведомления бухгалтерии, возможно, ручного вмешательства. Это редкий, но критичный бизнес-сценарий.
PaymentProcessingException — unchecked, так как ошибки процессинга (таймаут, недоступность шлюза) фатальны для текущей операции и обрабатываются централизованно через retry-механизм или circuit breaker.
InvalidPaymentRequestException — unchecked, так как передача невалидных данных — это ошибка вызывающего кода, которая должна быть исправлена до деплоя.
#Java #для_новичков #beginner #exception #checked #unchecked
👍3
Паттерн "Railway Oriented Programming" и альтернативы исключениям
В функциональном стиле, особенно при работе с Kotlin или современными Java-библиотеками, исключения часто заменяются на типы-результаты (Result types). Это позволяет явно моделировать ошибки в типовой системе без checked-исключений.
Пример с использованием библиотеки Vavr:
В этом подходе ошибки — это значения (values), а не исключительные ситуации. Клиентский код вынужден обрабатывать оба случая (success и failure) через pattern matching или методы fold, getOrElse, orElseThrow. Это устраняет проблему "забытого catch-блока", присущую unchecked-исключениям, без возврата к verbosity checked-исключений.
#Java #для_новичков #beginner #exception #checked #unchecked
В функциональном стиле, особенно при работе с Kotlin или современными Java-библиотеками, исключения часто заменяются на типы-результаты (Result types). Это позволяет явно моделировать ошибки в типовой системе без checked-исключений.
Пример с использованием библиотеки Vavr:
import io.vavr.control.Either;
import io.vavr.control.Try;
public Either<PaymentError, PaymentReceipt> processPayment(PaymentRequest request) {
return validateRequest(request)
.flatMap(this::authorizePayment)
.flatMap(this::executeTransfer)
.map(this::generateReceipt);
}
private Either<PaymentError, ValidatedRequest> validateRequest(PaymentRequest request) {
if (request.getAmount() <= 0) {
return Either.left(new PaymentError("INVALID_AMOUNT", "Amount must be positive"));
}
if (request.getCurrency() == null) {
return Either.left(new PaymentError("MISSING_CURRENCY", "Currency is required"));
}
return Either.right(new ValidatedRequest(request));
}
В этом подходе ошибки — это значения (values), а не исключительные ситуации. Клиентский код вынужден обрабатывать оба случая (success и failure) через pattern matching или методы fold, getOrElse, orElseThrow. Это устраняет проблему "забытого catch-блока", присущую unchecked-исключениям, без возврата к verbosity checked-исключений.
#Java #для_новичков #beginner #exception #checked #unchecked
👍4
Что выведет код?
#Tasks
import java.io.IOException;
public class Task100426 {
public static void main(String[] args) {
try {
method();
} catch (Exception e) {
System.out.println("Catch: " + e.getClass().getSimpleName());
}
}
static void method() {
try {
throw new IOException("IO");
} catch (IOException e) {
throw new RuntimeException("Runtime");
} finally {
return;
}
}
}
#Tasks
👍1
Варианты ответа:
Anonymous Quiz
7%
Catch: IOException
67%
Catch: RuntimeException
0%
Catch: NullPointerException
27%
Ничего не выведет
👍1
Что такое ReentrantLock и чем он отличается от synchronized? 🤓
Ответ:
ReentrantLock — это гибкая альтернатива блоку synchronized из пакета java.util.concurrent.locks.
Преимущества: возможность прервать ожидание (lockInterruptibly()), попытаться захватить lock без блокировки (tryLock()), создание честных блокировок (fairness).
Недостаток: нужно вручную освобождать в блоке finally. synchronized проще в использовании, менее подвержен ошибкам, но менее гибок.
Оба являются reentrant — поток может повторно захватить уже удерживаемый им же монитор/lock.
#собеседование
Ответ:
Преимущества: возможность прервать ожидание (lockInterruptibly()), попытаться захватить lock без блокировки (tryLock()), создание честных блокировок (fairness).
Недостаток: нужно вручную освобождать в блоке finally. synchronized проще в использовании, менее подвержен ошибкам, но менее гибок.
Оба являются reentrant — поток может повторно захватить уже удерживаемый им же монитор/lock.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4😱1
История технологии сегодня — 11 апреля
ℹ️ Кто родился в этот день
Ю́рий Никола́евич Калачников (11 апреля 1928, Кунгур — 4 октября 1998, Пермь) — советский конструктор артиллерийских систем. Разработаны: миномёт (артиллерийская часть) 2Б8 для 240-мм самоходного миномёта 2С4 «Тюльпан» (1972), 152-мм буксируемая пушка 2А36 «Гиацинт-Б» (1979) и её вариант — артиллерийская часть 2А37 для самоходной пушки 2С5 «Гиацинт-С» (1976). Семейство 120-мм артиллерийских орудий «Нона»: орудие 2А51 (артиллерийская часть) для самоходного орудия 2С9 «Нона-С» (1981), 120-мм буксируемое орудие 2Б16 «Нона-К» (1986), 120-мм орудие 2А60 для самоходного орудия 2С23 «Нона-СВК» (совместно с ЦНИИ «Буревестник») (1990). Боевые машины и транспортно-заряжающие машины реактивных систем залпового огня 9К57 «Ураган» (1976) и 9К58 «Смерч» (1986). Артиллерийская часть боевой машины и транспортно-заряжающей машины тяжёлой огнеметной системы ТОС-1 «Буратино».
Алекса́ндр Алекса́ндрович Андро́нов (29 марта [11 апреля] 1901 год, Москва — 31 октября 1952, Горький) — советский физик, механик и математик. Специалист в области электротехники, радиофизики и прикладной механики, создатель нового направления в теории колебаний и динамике систем, талантливый деятель высшей школы.
Никола́й Дми́триевич Девя́тков (29 марта [11 апреля] 1907 год, Вологда — 1 февраля 2001, Москва) — советский и российский учёный и организатор науки в области военной и медицинской электроники. Специалист в области разработки газоразрядных и сверхвысокочастотных приборов.
Масару Ибука (яп. 井深大 Ибука Масару, 11 апреля 1908, Никко — 19 декабря 1997, Токио) — японский инженер и предприниматель, один из основателей корпорации Sony. В 1946 году Ибука и Акио Морита совместно основали корпорацию Sony, которая первоначально называлась «Токийской телекоммуникационной инженерной корпорацией».
Э́ндрю Джон Уа́йлс (англ. Andrew John Wiles; род. 11 апреля 1953, Кембридж) — английский математик, профессор математики Принстонского университета, заведующий его кафедрой математики, член научного совета Института математики Клэя. Наиболее известен доказательством Великой теоремы Ферма.
🌐 Знаковые события
1970 — запущен Аполлон-13.
2017 — прекращение расширенной технической поддержки операционной системы Windows Vista.
#Biography #Birth_Date #Events #11апреля
Ю́рий Никола́евич Калачников (11 апреля 1928, Кунгур — 4 октября 1998, Пермь) — советский конструктор артиллерийских систем. Разработаны: миномёт (артиллерийская часть) 2Б8 для 240-мм самоходного миномёта 2С4 «Тюльпан» (1972), 152-мм буксируемая пушка 2А36 «Гиацинт-Б» (1979) и её вариант — артиллерийская часть 2А37 для самоходной пушки 2С5 «Гиацинт-С» (1976). Семейство 120-мм артиллерийских орудий «Нона»: орудие 2А51 (артиллерийская часть) для самоходного орудия 2С9 «Нона-С» (1981), 120-мм буксируемое орудие 2Б16 «Нона-К» (1986), 120-мм орудие 2А60 для самоходного орудия 2С23 «Нона-СВК» (совместно с ЦНИИ «Буревестник») (1990). Боевые машины и транспортно-заряжающие машины реактивных систем залпового огня 9К57 «Ураган» (1976) и 9К58 «Смерч» (1986). Артиллерийская часть боевой машины и транспортно-заряжающей машины тяжёлой огнеметной системы ТОС-1 «Буратино».
Алекса́ндр Алекса́ндрович Андро́нов (29 марта [11 апреля] 1901 год, Москва — 31 октября 1952, Горький) — советский физик, механик и математик. Специалист в области электротехники, радиофизики и прикладной механики, создатель нового направления в теории колебаний и динамике систем, талантливый деятель высшей школы.
Никола́й Дми́триевич Девя́тков (29 марта [11 апреля] 1907 год, Вологда — 1 февраля 2001, Москва) — советский и российский учёный и организатор науки в области военной и медицинской электроники. Специалист в области разработки газоразрядных и сверхвысокочастотных приборов.
Масару Ибука (яп. 井深大 Ибука Масару, 11 апреля 1908, Никко — 19 декабря 1997, Токио) — японский инженер и предприниматель, один из основателей корпорации Sony. В 1946 году Ибука и Акио Морита совместно основали корпорацию Sony, которая первоначально называлась «Токийской телекоммуникационной инженерной корпорацией».
Э́ндрю Джон Уа́йлс (англ. Andrew John Wiles; род. 11 апреля 1953, Кембридж) — английский математик, профессор математики Принстонского университета, заведующий его кафедрой математики, член научного совета Института математики Клэя. Наиболее известен доказательством Великой теоремы Ферма.
1970 — запущен Аполлон-13.
2017 — прекращение расширенной технической поддержки операционной системы Windows Vista.
#Biography #Birth_Date #Events #11апреля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
This media is not supported in your browser
VIEW IN TELEGRAM
https://devforge.ru/
Обновление залито, погнали тестить🧑💻
☝️Из важного:
- почту указывайте реальную, письмо с кодом туда уйдет (пока синхронно не пугайтесь).
- Шибко не спамим, все может сломаться))
- Access jwt токен вроде на час, а логику refresh токена я так и не протестил, может не работать. Просто напишите, что не работает, не нада какахами кидаться, я ж не супермен)))))
- Для мобилок пока все плохо)) Лучше с компа
В остальном жду ваших оценок😜
Oleborn
Обновление залито, погнали тестить
☝️Из важного:
- почту указывайте реальную, письмо с кодом туда уйдет (пока синхронно не пугайтесь).
- Шибко не спамим, все может сломаться))
- Access jwt токен вроде на час, а логику refresh токена я так и не протестил, может не работать. Просто напишите, что не работает, не нада какахами кидаться, я ж не супермен)))))
- Для мобилок пока все плохо)) Лучше с компа
В остальном жду ваших оценок😜
Oleborn
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
С 04.04 по 10.04
Предыдущий пост(с 28.03 по 03.04)
Воскресный мотивационный пост:
Наверно эту рубрику пора в топку истории...
Запись встреч/видео:
10. Timeout и Bulkhead: как не дать сервису утонуть в запросах?
Обучающие статьи:
Раздел 8. Stream API и функциональный стиль
Глава 8: За пределами коллекций. Бесконечность и I/O
I/O операции как потоки данных
Раздел 10. Исключения, логирование, отладка
Глава 1. Иерархия исключений (Exceptions)
Throwable — корень всех ошибок: Error, Exception, RuntimeException
Checked vs Unchecked исключения: когда что использовать.
[Совет по Java #023]
Тема: Тайм-ауты в параллельных стримах нельзя контролировать.
[Совет по Java #024]
Тема: ClassLoader не удаляет классы даже после сборки мусора.
Полезные статьи и видео:
Семь вещей, которые нельзя делать из-за стирания типов в Java
Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
Предыдущий пост(с 28.03 по 03.04)
Воскресный мотивационный пост:
Наверно эту рубрику пора в топку истории...
Запись встреч/видео:
10. Timeout и Bulkhead: как не дать сервису утонуть в запросах?
Обучающие статьи:
Раздел 8. Stream API и функциональный стиль
Глава 8: За пределами коллекций. Бесконечность и I/O
I/O операции как потоки данных
Раздел 10. Исключения, логирование, отладка
Глава 1. Иерархия исключений (Exceptions)
Throwable — корень всех ошибок: Error, Exception, RuntimeException
Checked vs Unchecked исключения: когда что использовать.
[Совет по Java #023]
Тема: Тайм-ауты в параллельных стримах нельзя контролировать.
[Совет по Java #024]
Тема: ClassLoader не удаляет классы даже после сборки мусора.
Полезные статьи и видео:
Семь вещей, которые нельзя делать из-за стирания типов в Java
Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
👍2
История технологии сегодня — 12 апреля
🚀 Международный день полёта человека в космос (на других официальных языках ООН: англ. International Day of Human Space Flight, исп. Día Internacional de los Vuelos Espaciales Tripulados, фр. Journée internationale du vol spatial habité) — памятная дата международного уровня в ознаменование начала космической эры для человечества. Ежегодно отмечается 12 апреля.
На корабле «Восток» 12 апреля 1961 года лётчик-космонавт СССР майор ВВС Юрий Алексеевич Гагарин совершил первый в мире пилотируемый полёт в космическое пространство. Старт корабля состоялся с советского космодрома Байконур в 9 часов 7 минут по московскому времени (06:07:00 UTC). Корабль выполнил один оборот вокруг Земли и совершил посадку в 10 часов 53 минуты (07:53:00 UTC) в районе деревни Смеловка Саратовской области. Длительность полёта составила 106 минут. Корабль стал и первым в мире управляемым космическим аппаратом, позволившим совершить полёт в космос.
ℹ️ Кто родился в этот день
Станисла́в Никола́евич Ко́нюхов (12 апреля 1937, с. Бекренево, Лежский район, Вологодская область, РСФСР — 3 апреля 2011) — учёный, инженер и конструктор в аэрокосмической области. Автор свыше 240 научных работ в области статики и динамики стойкости, рациональных способов обеспечения пространственной ориентации, механики взаимодействия твёрдых тел с препятствиями при гиперзвуковых скоростях.
🌐 Знаковые события
1903 — в Лондоне на маршрут вышел первый в мире городской автобус с двигателем внутреннего сгорания.
1961 — Гражданин СССР Юрий Гагарин на корабле «Восток-1» стал первым человеком, совершившим космический полёт.
1981 — в день 20-летия первого полёта человека в космос стартовал американский корабль «Колумбия». Первый пилотируемый полёт в космос по программе «Спейс шаттл».
1995 — запущен каталог «Yahoo!», быстро ставший одним из самых популярных в мире.
#Biography #Birth_Date #Events #12апреля
На корабле «Восток» 12 апреля 1961 года лётчик-космонавт СССР майор ВВС Юрий Алексеевич Гагарин совершил первый в мире пилотируемый полёт в космическое пространство. Старт корабля состоялся с советского космодрома Байконур в 9 часов 7 минут по московскому времени (06:07:00 UTC). Корабль выполнил один оборот вокруг Земли и совершил посадку в 10 часов 53 минуты (07:53:00 UTC) в районе деревни Смеловка Саратовской области. Длительность полёта составила 106 минут. Корабль стал и первым в мире управляемым космическим аппаратом, позволившим совершить полёт в космос.
Станисла́в Никола́евич Ко́нюхов (12 апреля 1937, с. Бекренево, Лежский район, Вологодская область, РСФСР — 3 апреля 2011) — учёный, инженер и конструктор в аэрокосмической области. Автор свыше 240 научных работ в области статики и динамики стойкости, рациональных способов обеспечения пространственной ориентации, механики взаимодействия твёрдых тел с препятствиями при гиперзвуковых скоростях.
1903 — в Лондоне на маршрут вышел первый в мире городской автобус с двигателем внутреннего сгорания.
1961 — Гражданин СССР Юрий Гагарин на корабле «Восток-1» стал первым человеком, совершившим космический полёт.
1981 — в день 20-летия первого полёта человека в космос стартовал американский корабль «Колумбия». Первый пилотируемый полёт в космос по программе «Спейс шаттл».
1995 — запущен каталог «Yahoo!», быстро ставший одним из самых популярных в мире.
#Biography #Birth_Date #Events #12апреля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Что случилось и почему сайт не работал или хронология одного хренового утра
Сразу к делу: сайт лежал намертво.
Не просто не открывалась страница, а вообще никакого признака жизни извне.
При этом я зашел через VNC (прямую консоль провайдера) и увидел, что сервер внутри работает. Файлы на месте, база цела, контейнеры Docker крутятся. Но снаружи — бетонная стена.
Ниже расскажу, что именно произошло, почему техподдержка трижды предлагала мне просто все переустановить и как в итоге удалось вытащить проект с того света без потери данных.
Часть 1. Симптомы, которые сбивали с толку
Первый звоночек: SSH не подключается. Таймаут. Первая мысль может порт сменился или фаервол взбесился. Захожу через VNC и вижу странную картину. Фаервол чистый. SSH демон запущен. Но соединения извне нет вообще.
Делаю пинг до гугловской восьмерки и вижу заветные слова: Destination Host Unreachable. Это уже совсем плохой звоночек. Он означает, что сервер не просто не видит интернет, он не видит даже собственный шлюз провайдера. Он как будто в вакууме.
Дальше больше. Проверяю сетевые настройки: IP на месте, маска правильная, шлюз прописан. Сбрасываю интерфейс, перезагружаю сервер, чищу ARP-таблицу. Ноль реакции.
Часть 2. Техподдержка и стадия отрицания
Пишу в техподдержку. Объясняю ситуацию: консоль есть, сервер жив, но сети нет. В ответ получаю классику: "Переустановите операционную систему".
Переустановка ОС при такой проблеме это как менять двигатель у машины, у которой просто отвалилось колесо. Данные бы улетели, все настройки nginx и docker пришлось бы поднимать с нуля, но связь бы не появилась, потому что проблема была глубже.
Начинается битва аргументов. Привожу вывод команды ip neigh show, где напротив адреса шлюза красуется статус FAILED. Это железное доказательство того, что обрыв на канальном уровне, то есть на стороне виртуального коммутатора провайдера.
Часть 3. Смена IP и миграция
Чтобы отвязаться от настойчивых просьб переустановить систему, соглашаюсь на предложение сменить IP-адрес. Меняют. Прописываю новый адрес вручную в консоли. Результат тот же — Destination Host Unreachable. Это окончательно подтверждает: проблема не в софте, а в виртуальном железе, к которому прицеплен VPS.
Только после этого неожиданно сервер мигрируют на другую физическую ноду.
И о чудо. Пинг до восьмерки пошел. Сеть ожила.
Часть 4. Оживление пациента
Казалось бы, победа. Но это был только начало.
После миграции сайт все равно не открывался, а SSH валился с ошибкой Connection refused.
Выяснилось, что после миграции демон SSH просто отключился и не встал в автозагрузку.
Дальше пошла борьба с Nginx. Конфиги, которые прекрасно работали на старом месте, здесь встали колом. Оказалось, что запросы улетали в неправильный блок сервера и рвались с ошибкой Empty reply from server. Пришлось перелопатить конфиги, убрать лишние редиректы и явно прописать, что сайт должен слушаться не только по домену, но и просто по IP.
Затем всплыла история с сертификатами. Let's Encrypt честно выдал новые ключи, но браузер упорно не хотел показывать сайт по HTTPS.
Часть 5. Финальный босс — кэш браузера
Тут началась настоящая мистика. По IP через HTTP все грузилось идеально. А по домену devforge.ru — белый экран. Ни ошибок в консоли, ни проблем с сетью.
Оказалось, что это HSTS. Механизм безопасности браузера, который намертво запомнил старые настройки еще с прошлого IP. Браузер тупо блокировал загрузку ресурсов, считая, что сайт подменили.
Открываю то же самое в режиме инкогнито — и все работает как часы.
Выяснилось: сервер был полностью исправен уже несколько часов, а проблема сидела в кэше на стороне клиента (я ебалай).
Итог
Сервер перенесен на новую ноду. Связка Nginx, Docker и API работает стабильно. DNS обновлены. SSL сертификаты свежие.
Если у вас вдруг сейчас сайт не грузится или выглядит странно — просто почистите кэш браузера или откройте страницу в режиме инкогнито. Это уберет остатки старых редиректов.
Если кто пытался зайти на Devforge.ru, но не мог, спасибо за терпение.
Проект снова в строю и стал немного надежнее.
А я маленько вахуе 🤪
Сразу к делу: сайт лежал намертво.
Не просто не открывалась страница, а вообще никакого признака жизни извне.
При этом я зашел через VNC (прямую консоль провайдера) и увидел, что сервер внутри работает. Файлы на месте, база цела, контейнеры Docker крутятся. Но снаружи — бетонная стена.
Ниже расскажу, что именно произошло, почему техподдержка трижды предлагала мне просто все переустановить и как в итоге удалось вытащить проект с того света без потери данных.
Часть 1. Симптомы, которые сбивали с толку
Первый звоночек: SSH не подключается. Таймаут. Первая мысль может порт сменился или фаервол взбесился. Захожу через VNC и вижу странную картину. Фаервол чистый. SSH демон запущен. Но соединения извне нет вообще.
Делаю пинг до гугловской восьмерки и вижу заветные слова: Destination Host Unreachable. Это уже совсем плохой звоночек. Он означает, что сервер не просто не видит интернет, он не видит даже собственный шлюз провайдера. Он как будто в вакууме.
Дальше больше. Проверяю сетевые настройки: IP на месте, маска правильная, шлюз прописан. Сбрасываю интерфейс, перезагружаю сервер, чищу ARP-таблицу. Ноль реакции.
Часть 2. Техподдержка и стадия отрицания
Пишу в техподдержку. Объясняю ситуацию: консоль есть, сервер жив, но сети нет. В ответ получаю классику: "Переустановите операционную систему".
Переустановка ОС при такой проблеме это как менять двигатель у машины, у которой просто отвалилось колесо. Данные бы улетели, все настройки nginx и docker пришлось бы поднимать с нуля, но связь бы не появилась, потому что проблема была глубже.
Начинается битва аргументов. Привожу вывод команды ip neigh show, где напротив адреса шлюза красуется статус FAILED. Это железное доказательство того, что обрыв на канальном уровне, то есть на стороне виртуального коммутатора провайдера.
Часть 3. Смена IP и миграция
Чтобы отвязаться от настойчивых просьб переустановить систему, соглашаюсь на предложение сменить IP-адрес. Меняют. Прописываю новый адрес вручную в консоли. Результат тот же — Destination Host Unreachable. Это окончательно подтверждает: проблема не в софте, а в виртуальном железе, к которому прицеплен VPS.
Только после этого неожиданно сервер мигрируют на другую физическую ноду.
И о чудо. Пинг до восьмерки пошел. Сеть ожила.
Часть 4. Оживление пациента
Казалось бы, победа. Но это был только начало.
После миграции сайт все равно не открывался, а SSH валился с ошибкой Connection refused.
Выяснилось, что после миграции демон SSH просто отключился и не встал в автозагрузку.
Дальше пошла борьба с Nginx. Конфиги, которые прекрасно работали на старом месте, здесь встали колом. Оказалось, что запросы улетали в неправильный блок сервера и рвались с ошибкой Empty reply from server. Пришлось перелопатить конфиги, убрать лишние редиректы и явно прописать, что сайт должен слушаться не только по домену, но и просто по IP.
Затем всплыла история с сертификатами. Let's Encrypt честно выдал новые ключи, но браузер упорно не хотел показывать сайт по HTTPS.
Часть 5. Финальный босс — кэш браузера
Тут началась настоящая мистика. По IP через HTTP все грузилось идеально. А по домену devforge.ru — белый экран. Ни ошибок в консоли, ни проблем с сетью.
Оказалось, что это HSTS. Механизм безопасности браузера, который намертво запомнил старые настройки еще с прошлого IP. Браузер тупо блокировал загрузку ресурсов, считая, что сайт подменили.
Открываю то же самое в режиме инкогнито — и все работает как часы.
Выяснилось: сервер был полностью исправен уже несколько часов, а проблема сидела в кэше на стороне клиента
Итог
Сервер перенесен на новую ноду. Связка Nginx, Docker и API работает стабильно. DNS обновлены. SSL сертификаты свежие.
Если у вас вдруг сейчас сайт не грузится или выглядит странно — просто почистите кэш браузера или откройте страницу в режиме инкогнито. Это уберет остатки старых редиректов.
Если кто пытался зайти на Devforge.ru, но не мог, спасибо за терпение.
Проект снова в строю и стал немного надежнее.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🤯4
История технологии сегодня — 13 апреля
ℹ️ Кто родился в этот день
Джеремайя Пол (Джерри) Острайкер (англ. Jeremiah Paul «Jerry» Ostriker; 13 апреля 1937, Нью-Йорк — 6 апреля 2025, там же) — американский теоретик-астрофизик и космолог, основоположник теории тёмного вещества. Автор более 500 научных публикаций в сфере космологии, особо уделял внимание темам, в которых применяются сложные математические вычисления. Основными темами исследований Острайкера были тёмное вещество и тёмная энергия, тепло-горячая межгалактическая среда, формирование галактик, рост чёрных дыр и взаимодействие квазаров с окружающим пространством.
Ро́берт Алекса́ндр Уо́тсон-Уотт (англ. Robert Alexander Watson-Watt; 13 апреля 1892 — 5 декабря 1973) — шотландский физик, один из пионеров в области работ по радиолокации. Сконструировал одно из первых устройств, предназначенных для радиолокации воздушных объектов и получил первый патент на изобретение подобной системы в 1934 году, а 26 февраля 1935 года успешно продемонстрировал своё изобретение, которое могло обнаружить самолёт на расстоянии 64 км.
Антонио Санти Джузеппе Меуччи (итал. Antonio Santi Giuseppe Meucci; 13 апреля 1808 — 18 октября 1889) — итальянский учёный, являющийся изобретателем телефона. Именно он в 1860 году пришёл к выводу о возможности превращения звуковых колебаний в электрические импульсы, что позволяет передавать голос на расстояние с помощью проводов.
🌐 Знаковые события
1960 — Соединенные Штаты запускают Transit 1-B, первую в мире спутниковую навигационную систему.
#Biography #Birth_Date #Events #13апреля
Джеремайя Пол (Джерри) Острайкер (англ. Jeremiah Paul «Jerry» Ostriker; 13 апреля 1937, Нью-Йорк — 6 апреля 2025, там же) — американский теоретик-астрофизик и космолог, основоположник теории тёмного вещества. Автор более 500 научных публикаций в сфере космологии, особо уделял внимание темам, в которых применяются сложные математические вычисления. Основными темами исследований Острайкера были тёмное вещество и тёмная энергия, тепло-горячая межгалактическая среда, формирование галактик, рост чёрных дыр и взаимодействие квазаров с окружающим пространством.
Ро́берт Алекса́ндр Уо́тсон-Уотт (англ. Robert Alexander Watson-Watt; 13 апреля 1892 — 5 декабря 1973) — шотландский физик, один из пионеров в области работ по радиолокации. Сконструировал одно из первых устройств, предназначенных для радиолокации воздушных объектов и получил первый патент на изобретение подобной системы в 1934 году, а 26 февраля 1935 года успешно продемонстрировал своё изобретение, которое могло обнаружить самолёт на расстоянии 64 км.
Антонио Санти Джузеппе Меуччи (итал. Antonio Santi Giuseppe Meucci; 13 апреля 1808 — 18 октября 1889) — итальянский учёный, являющийся изобретателем телефона. Именно он в 1860 году пришёл к выводу о возможности превращения звуковых колебаний в электрические импульсы, что позволяет передавать голос на расстояние с помощью проводов.
1960 — Соединенные Штаты запускают Transit 1-B, первую в мире спутниковую навигационную систему.
#Biography #Birth_Date #Events #13апреля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
[Совет по Java #025]
Тема: ThreadLocal может вызвать утечку в серверах приложений.
Проблема: В серверах приложений (Tomcat, Jetty, WildFly) потоки из пула переиспользуются между запросами.
ThreadLocal хранит данные, привязанные к конкретному потоку. Если после обработки запроса не вызвать remove(), данные останутся в потоке навсегда. При следующем запросе, который получит тот же поток, код увидит "грязные" данные от предыдущего запроса, что приводит к непредсказуемому поведению — утечке контекста безопасности, некорректным настройкам локали, перемешиванию данных разных пользователей.
Более того, если загруженный класс (например, из веб-приложения) хранится в ThreadLocal, а поток продолжает жить, это создает классическую утечку памяти ClassLoader — приложение не может быть выгружено.
Решение: Всегда вызывайте ThreadLocal.remove() после использования, особенно в веб-среде.
Лучшая практика — оборачивать использование ThreadLocal в блок try-finally. Для фильтров и перехватчиков используйте один централизованный механизм очистки. Рассмотрите альтернативы: передача контекста явно через параметры методов, использование ScopedValue (Java 20+ incubator, Java 21+ preview), которое автоматически очищается.
Объяснение: Пул потоков в серверах приложений создает ограниченное количество потоков, которые обрабатывают тысячи запросов последовательно.
ThreadLocal хранит значение в массиве ThreadLocalMap внутри объекта Thread. Если не вызвать remove(), ссылка на значение остается в этом массиве. При следующем использовании того же потока get() вернет старое значение. Даже если ссылка на объект в ThreadLocal станет слабой (как у ThreadLocal по умолчанию), она все равно будет достижима через Thread.currentThread(), пока поток жив.
Это приводит к двум проблемам: логическая утечка (неправильные данные) и физическая утечка (классы из веб-приложения не выгружаются).
Правило простое: для каждого set() должен быть соответствующий remove() в том же потоке. Java 21 предлагает ScopedValue как иммутабельную и автоматически очищаемую альтернативу.
#Java #советы
Тема: ThreadLocal может вызвать утечку в серверах приложений.
Проблема: В серверах приложений (Tomcat, Jetty, WildFly) потоки из пула переиспользуются между запросами.
ThreadLocal хранит данные, привязанные к конкретному потоку. Если после обработки запроса не вызвать remove(), данные останутся в потоке навсегда. При следующем запросе, который получит тот же поток, код увидит "грязные" данные от предыдущего запроса, что приводит к непредсказуемому поведению — утечке контекста безопасности, некорректным настройкам локали, перемешиванию данных разных пользователей.
Более того, если загруженный класс (например, из веб-приложения) хранится в ThreadLocal, а поток продолжает жить, это создает классическую утечку памяти ClassLoader — приложение не может быть выгружено.
Решение: Всегда вызывайте ThreadLocal.remove() после использования, особенно в веб-среде.
Лучшая практика — оборачивать использование ThreadLocal в блок try-finally. Для фильтров и перехватчиков используйте один централизованный механизм очистки. Рассмотрите альтернативы: передача контекста явно через параметры методов, использование ScopedValue (Java 20+ incubator, Java 21+ preview), которое автоматически очищается.
public class ThreadLocalLeak {
//Антипаттерн: ThreadLocal без очистки
private static final ThreadLocal<UserContext> CURRENT_USER = new ThreadLocal<>();
public static void processRequestBad(User user) {
CURRENT_USER.set(new UserContext(user)); // Установили
// ... обработка запроса
// Забыли remove() — данные останутся в потоке навсегда
}
//Решение: try-finally с remove()
public static void processRequestGood(User user) {
try {
CURRENT_USER.set(new UserContext(user));
// ... обработка запроса
} finally {
CURRENT_USER.remove(); // Гарантированная очистка
}
}
// Демонстрация утечки
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(2);
// Плохой вариант
for (int i = 0; i < 10; i++) {
final int requestId = i;
executor.submit(() -> {
processRequestBad(new User("User" + requestId));
});
}
Thread.sleep(1000);
// Теперь в потоках пула остались старые данные
executor.submit(() -> {
UserContext context = CURRENT_USER.get(); // Может вернуть данные от старого запроса!
System.out.println("Остались данные: " + context);
});
executor.shutdown();
}
// Для веб-фильтра (Spring-стиль)
public static class WebFilter {
public void doFilter(Request request, FilterChain chain) {
try {
// Установка контекста из запроса
UserContext.setCurrent(request.getUser());
chain.proceed();
} finally {
UserContext.clear(); // Обязательная очистка после каждого запроса
}
}
}
}Объяснение: Пул потоков в серверах приложений создает ограниченное количество потоков, которые обрабатывают тысячи запросов последовательно.
ThreadLocal хранит значение в массиве ThreadLocalMap внутри объекта Thread. Если не вызвать remove(), ссылка на значение остается в этом массиве. При следующем использовании того же потока get() вернет старое значение. Даже если ссылка на объект в ThreadLocal станет слабой (как у ThreadLocal по умолчанию), она все равно будет достижима через Thread.currentThread(), пока поток жив.
Это приводит к двум проблемам: логическая утечка (неправильные данные) и физическая утечка (классы из веб-приложения не выгружаются).
Правило простое: для каждого set() должен быть соответствующий remove() в том же потоке. Java 21 предлагает ScopedValue как иммутабельную и автоматически очищаемую альтернативу.
#Java #советы
👍5
Что выведет код?
#Tasks
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Task130426 {
static class UserContext130426 {
String userId;
UserContext130426(String userId) { this.userId = userId; }
}
static ThreadLocal<UserContext130426> currentUser = new ThreadLocal<>();
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(() -> {
currentUser.set(new UserContext130426("user1"));
System.out.print(currentUser.get().userId + " ");
});
executor.submit(() -> {
UserContext130426 ctx = currentUser.get();
System.out.println(ctx == null ? "null" : ctx.userId);
});
executor.shutdown();
}
}
#Tasks
👍1
👍2
Что такое Semaphore? 🤓
Ответ:
Semaphore (семафор) — это средство синхронизации, которое ограничивает количество потоков, имеющих доступ к определенному ресурсу или участку кода.
Семафор поддерживает счетчик разрешений. Поток запрашивает разрешение методом acquire() (счетчик уменьшается) и освобождает методом release() (счетчик увеличивается).
Если разрешений нет, поток блокируется. Битовый семафор (счетчик 1) работает как мьютекс (lock). Семафоры часто используются для ограничения нагрузки (throttling).
#собеседование
Ответ:
Семафор поддерживает счетчик разрешений. Поток запрашивает разрешение методом acquire() (счетчик уменьшается) и освобождает методом release() (счетчик увеличивается).
Если разрешений нет, поток блокируется. Битовый семафор (счетчик 1) работает как мьютекс (lock). Семафоры часто используются для ограничения нагрузки (throttling).
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
История технологии сегодня — 14 апреля
ℹ️ Кто родился в этот день
Серге́й Ива́нович Мо́син (2 [14] апреля 1849, Рамонь — 26 января [8 февраля] 1902, Сестрорецк) — русский конструктор и организатор производства стрелкового оружия. Генерал-майор Русской императорской армии.
В 1883 году Мосин разработал свои первые магазинные винтовки. Так, он усовершенствовал винтовку Бердана, приделав к ней магазин на восемь патронов. 16 апреля 1891 года был утверждён образец «повторительной» четырёхтактной винтовки со серединным магазином калибра 3 линии (7,62 мм), основу которой разработал Мосин. Она получила название «Трёхлинейная винтовка образца 1891 года». В 1900 году на Всемирной выставке в Париже российская «малокалиберная» трёхлинейная штатная винтовка получила Гран-При. Винтовки и карабины системы Мосина нескольких модификаций производилась в России и СССР до 1947 года и находились на вооружении до середины 1970-х годов. После Второй мировой войны винтовки и карабины Мосина производились по лицензии в ПНР, ВНР, РНР.
Юкихиро Мацумо́то (яп. 松本行弘, чаще яп. まつもとゆきひろ, также известный как Matz, род. 14 апреля 1965) — японский разработчик свободного ПО, создатель языка программирования Ruby.
В интервью «Japan Inc.» он говорил, что сам учился программировать ещё до окончания школы. Он окончил университет города Цукуба, где он занимался исследованиями языков программирования и компиляторов. С 2006 года возглавляет отдел исследований и разработок Network Applied Communication Laboratory, японский системный интегратор свободного ПО.
Христиа́н Гю́йгенс ван Зёйлихем (нид. Christiaan Huygens МФА: [ˈkrɪstijaːn ˈɦœyɣə(n)s]о файле; 14 апреля 1629, Гаага — 8 июля 1695, там же) — голландский механик, физик, математик, астроном и изобретатель. Первый иностранный член Лондонского королевского общества (1663), член Французской академии наук с момента её основания (1666) и её первый президент (1666—1681).
Один из основоположников теоретической механики и теории вероятностей. Внёс значительный вклад в оптику, молекулярную физику, астрономию, геометрию, часовое дело. Открыл кольца Сатурна и Титан (спутник Сатурна). Изобрёл первую практически применимую модель часов с маятником. Положил начало волновой оптике.
🌐 Знаковые события
1932 — в кембриджской лаборатории Резерфорда физики Кокрофт и Уолтон впервые добились искусственной ядерной реакции.
1983 — первый радиотелефон начал продаваться в Великобритании.
2003 — учёные объявили о завершении основных работ по расшифровке генома человека.
#Biography #Birth_Date #Events #14апреля
Серге́й Ива́нович Мо́син (2 [14] апреля 1849, Рамонь — 26 января [8 февраля] 1902, Сестрорецк) — русский конструктор и организатор производства стрелкового оружия. Генерал-майор Русской императорской армии.
В 1883 году Мосин разработал свои первые магазинные винтовки. Так, он усовершенствовал винтовку Бердана, приделав к ней магазин на восемь патронов. 16 апреля 1891 года был утверждён образец «повторительной» четырёхтактной винтовки со серединным магазином калибра 3 линии (7,62 мм), основу которой разработал Мосин. Она получила название «Трёхлинейная винтовка образца 1891 года». В 1900 году на Всемирной выставке в Париже российская «малокалиберная» трёхлинейная штатная винтовка получила Гран-При. Винтовки и карабины системы Мосина нескольких модификаций производилась в России и СССР до 1947 года и находились на вооружении до середины 1970-х годов. После Второй мировой войны винтовки и карабины Мосина производились по лицензии в ПНР, ВНР, РНР.
Юкихиро Мацумо́то (яп. 松本行弘, чаще яп. まつもとゆきひろ, также известный как Matz, род. 14 апреля 1965) — японский разработчик свободного ПО, создатель языка программирования Ruby.
В интервью «Japan Inc.» он говорил, что сам учился программировать ещё до окончания школы. Он окончил университет города Цукуба, где он занимался исследованиями языков программирования и компиляторов. С 2006 года возглавляет отдел исследований и разработок Network Applied Communication Laboratory, японский системный интегратор свободного ПО.
Христиа́н Гю́йгенс ван Зёйлихем (нид. Christiaan Huygens МФА: [ˈkrɪstijaːn ˈɦœyɣə(n)s]о файле; 14 апреля 1629, Гаага — 8 июля 1695, там же) — голландский механик, физик, математик, астроном и изобретатель. Первый иностранный член Лондонского королевского общества (1663), член Французской академии наук с момента её основания (1666) и её первый президент (1666—1681).
Один из основоположников теоретической механики и теории вероятностей. Внёс значительный вклад в оптику, молекулярную физику, астрономию, геометрию, часовое дело. Открыл кольца Сатурна и Титан (спутник Сатурна). Изобрёл первую практически применимую модель часов с маятником. Положил начало волновой оптике.
1932 — в кембриджской лаборатории Резерфорда физики Кокрофт и Уолтон впервые добились искусственной ядерной реакции.
1983 — первый радиотелефон начал продаваться в Великобритании.
2003 — учёные объявили о завершении основных работ по расшифровке генома человека.
#Biography #Birth_Date #Events #14апреля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Раздел 9. Исключения, логирование, отладка
Глава 1. Иерархия исключений (Exceptions)
try-catch-finally – правильная обработка и освобождение ресурсов
Исторический контекст: до Java 7
До появления Java 7 в 2011 году механизм try-catch-finally был единственным способом гарантировать выполнение cleanup-кода независимо от того, как завершился основной блок операций. Этот паттерн применялся для закрытия файловых потоков, сетевых соединений, освобождения блокировок и любых других ресурсов, требующих явного освобождения.
Однако этот подход был чрезвычайно многословным и подверженным ошибкам. Каждый ресурс требовал отдельной переменной, объявленной вне блока try, проверки на null в finally, и вложенных try-catch блоков для обработки исключений при самом закрытии ресурса. Это создавало "pyramid of doom" — визуально громоздкую структуру кода, где бизнес-логика терялась среди шаблонного кода управления ресурсами.
Механика выполнения: как JVM обрабатывает finally
На уровне байткода JVM блок finally реализован не как отдельная конструкция языка, а через механизм инлайнинга и таблиц исключений. Компилятор Java дублирует байткод finally-блока в каждой точке выхода из try и связанных catch-блоков, а также добавляет специальные записи в exception table для гарантии выполнения даже при неперехваченных исключениях.
Рассмотрим простой пример и его байткод-представление:
Компилятор генерирует байткод, где инструкции cleanup() дублируются в трех местах: при нормальном завершении try, при выходе через return, и в специальном catch-all обработчике для неперехваченных исключений. Exception table метода содержит запись from: 0, to: 4, target: 8, type: any, которая перехватывает любое исключение, выполняет cleanup, и перевыбрасывает исходное исключение .
В современных версиях Java (начиная с Java 6) компилятор использует полный инлайнинг байткода finally-блока. Ранее, до Java 6, применялись мини-подпрограммы (mini-subroutines) с инструкциями jsr (jump subroutine) и ret (return from subroutine), которые вызывали общий блок кода из разных точек . Этот подход был отменен из-за сложностей верификации байткода и ограничений на оптимизацию.
Паттерн управления ресурсами: классический подход
Классический паттерн освобождения ресурсов через try-finally требовал строгой дисциплины.
Рассмотрим корректную реализацию для одного ресурса:
Этот код содержит несколько критически важных элементов. Переменная reader объявлена вне блока try для доступности в finally. Проверка на null обязательна, так как если конструктор FileReader выбросит исключение (например, файл не найден), переменная reader останется неинициализированной. Блок finally выполняется всегда, даже если readLine() выбросит исключение или метод выполнит ранний return.
Сложность экспоненциально растет с количеством ресурсов. Для двух ресурсов требуется уже четыре уровня вложенности:
#Java #для_новичков #beginner #exception #try_catch_finally
Глава 1. Иерархия исключений (Exceptions)
try-catch-finally – правильная обработка и освобождение ресурсов
Исторический контекст: до Java 7
До появления Java 7 в 2011 году механизм try-catch-finally был единственным способом гарантировать выполнение cleanup-кода независимо от того, как завершился основной блок операций. Этот паттерн применялся для закрытия файловых потоков, сетевых соединений, освобождения блокировок и любых других ресурсов, требующих явного освобождения.
Однако этот подход был чрезвычайно многословным и подверженным ошибкам. Каждый ресурс требовал отдельной переменной, объявленной вне блока try, проверки на null в finally, и вложенных try-catch блоков для обработки исключений при самом закрытии ресурса. Это создавало "pyramid of doom" — визуально громоздкую структуру кода, где бизнес-логика терялась среди шаблонного кода управления ресурсами.
Механика выполнения: как JVM обрабатывает finally
На уровне байткода JVM блок finally реализован не как отдельная конструкция языка, а через механизм инлайнинга и таблиц исключений. Компилятор Java дублирует байткод finally-блока в каждой точке выхода из try и связанных catch-блоков, а также добавляет специальные записи в exception table для гарантии выполнения даже при неперехваченных исключениях.
Рассмотрим простой пример и его байткод-представление:
public void simpleTryFinally() {
try {
processData();
} finally {
cleanup();
}
}Компилятор генерирует байткод, где инструкции cleanup() дублируются в трех местах: при нормальном завершении try, при выходе через return, и в специальном catch-all обработчике для неперехваченных исключений. Exception table метода содержит запись from: 0, to: 4, target: 8, type: any, которая перехватывает любое исключение, выполняет cleanup, и перевыбрасывает исходное исключение .
В современных версиях Java (начиная с Java 6) компилятор использует полный инлайнинг байткода finally-блока. Ранее, до Java 6, применялись мини-подпрограммы (mini-subroutines) с инструкциями jsr (jump subroutine) и ret (return from subroutine), которые вызывали общий блок кода из разных точек . Этот подход был отменен из-за сложностей верификации байткода и ограничений на оптимизацию.
Паттерн управления ресурсами: классический подход
Классический паттерн освобождения ресурсов через try-finally требовал строгой дисциплины.
Рассмотрим корректную реализацию для одного ресурса:
public String readFile(String path) throws IOException {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(path));
return reader.readLine();
} finally {
if (reader != null) {
reader.close();
}
}
}Этот код содержит несколько критически важных элементов. Переменная reader объявлена вне блока try для доступности в finally. Проверка на null обязательна, так как если конструктор FileReader выбросит исключение (например, файл не найден), переменная reader останется неинициализированной. Блок finally выполняется всегда, даже если readLine() выбросит исключение или метод выполнит ранний return.
Сложность экспоненциально растет с количеством ресурсов. Для двух ресурсов требуется уже четыре уровня вложенности:
public void copyFile(String sourcePath, String destPath) throws IOException {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(sourcePath);
try {
fos = new FileOutputStream(destPath);
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
} finally {
if (fos != null) {
fos.close();
}
}
} finally {
if (fis != null) {
fis.close();
}
}
}#Java #для_новичков #beginner #exception #try_catch_finally
👍4