Что такое 🤓
Ответ:
Thread.onSpinWait() — метод, который подсказывает JVM и процессору, что текущий поток выполняет активное ожидание (busy-wait).
Это позволяет процессору оптимизировать энергопотребление и эффективность, например, переключить ядро в режим пониженного потребления.
Используется в низкоуровневых lock-free алгоритмах (например, ожидание в AbstractQueuedSynchronizer). Обычно вызывается внутри цикла, где ожидается некоторое условие, но блокировка неэффективна.
Улучшает производительность по сравнению с пустым циклом.
#собеседование
Thread.onSpinWait() (Java 9)? Ответ:
Это позволяет процессору оптимизировать энергопотребление и эффективность, например, переключить ядро в режим пониженного потребления.
Используется в низкоуровневых lock-free алгоритмах (например, ожидание в AbstractQueuedSynchronizer). Обычно вызывается внутри цикла, где ожидается некоторое условие, но блокировка неэффективна.
Улучшает производительность по сравнению с пустым циклом.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
История технологии сегодня — 22 июля
ℹ️ Кто родился в этот день
Па́вел О́сипович Сухо́й (бел. Павел Восіпавіч Сухі; 10 [22] июля 1895, Глубокое, Дисненский уезд, Виленская губерния, Российская империя (ныне Витебская область, Беларусь) — 15 сентября 1975, Москва, СССР) — советский авиаконструктор, доктор технических наук, один из основателей советской реактивной и сверхзвуковой авиации.
Гу́став Лю́двиг Герц (нем. Gustav Ludwig Hertz; 22 июля 1887, Гамбург — 30 октября 1975, Берлин) — немецкий физик, лауреат Нобелевской премии по физике в 1925 году «за открытие законов соударения электрона с атомом» (совместно с Джеймсом Франком).
Габриэ́ль Ламе́ (фр. Gabriel Lamé; 22 июля 1795, Тур — 1 мая 1870, Париж) — французский математик, механик, физик и инженер, член-корреспондент Петербургской академии наук (1829), член Парижской академии наук (1843), профессор Политехнической школы (1832—1863) и Парижского университета (1848—1863). В 1820—1831 годах работал в России, в петербургском Институте Корпуса инженеров путей сообщения. Основные труды — по математической физике и теории упругости. Разработал общую теорию криволинейных координат (1833), ввёл так называемые коэффициенты Ламе (1859) и специальный класс функций (1839, функции Ламе). В честь него названы параметры Ламе в теории упругости.
🌐 Знаковые события
1961 — первый полёт первого советского экраноплана «СМ-1».
1996 — вышла компьютерная игра Quake.
#Biography #Birth_Date #Events #22июля
Па́вел О́сипович Сухо́й (бел. Павел Восіпавіч Сухі; 10 [22] июля 1895, Глубокое, Дисненский уезд, Виленская губерния, Российская империя (ныне Витебская область, Беларусь) — 15 сентября 1975, Москва, СССР) — советский авиаконструктор, доктор технических наук, один из основателей советской реактивной и сверхзвуковой авиации.
Гу́став Лю́двиг Герц (нем. Gustav Ludwig Hertz; 22 июля 1887, Гамбург — 30 октября 1975, Берлин) — немецкий физик, лауреат Нобелевской премии по физике в 1925 году «за открытие законов соударения электрона с атомом» (совместно с Джеймсом Франком).
Габриэ́ль Ламе́ (фр. Gabriel Lamé; 22 июля 1795, Тур — 1 мая 1870, Париж) — французский математик, механик, физик и инженер, член-корреспондент Петербургской академии наук (1829), член Парижской академии наук (1843), профессор Политехнической школы (1832—1863) и Парижского университета (1848—1863). В 1820—1831 годах работал в России, в петербургском Институте Корпуса инженеров путей сообщения. Основные труды — по математической физике и теории упругости. Разработал общую теорию криволинейных координат (1833), ввёл так называемые коэффициенты Ламе (1859) и специальный класс функций (1839, функции Ламе). В честь него названы параметры Ламе в теории упругости.
1961 — первый полёт первого советского экраноплана «СМ-1».
1996 — вышла компьютерная игра Quake.
#Biography #Birth_Date #Events #22июля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
[Совет по Java #063]
Тема:
Проблема: Метод
На разных платформах это может быть CP1251 (Windows), UTF-8 (Linux), MacRoman (macOS) или другие. Это приводит к тому, что одно и то же приложение на разных машинах генерирует разные байтовые последовательности для одинаковых строк, что вызывает ошибки при передаче данных по сети, записи в файлы или взаимодействии с внешними системами. Особенно критично для символов вне ASCII (кириллица, иероглифы) — они могут быть испорчены или потеряны. Даже если сейчас всё работает, при смене окружения (например, при деплое на сервер с другой кодировкой) приложение внезапно ломается, и диагностика затруднена, так как проблема проявляется только в определённых условиях.
Решение: Всегда указывайте кодировку явно с помощью
Предпочтительно использовать константы из
Для проектов, ориентированных на международное взаимодействие, UTF-8 является стандартом де-факто.
Объяснение: Кодировка по умолчанию определяется системным свойством
Однако это глобальная настройка, которая может быть неочевидна для других разработчиков, а её изменение может повлиять на другие части системы (например, чтение файлов). Явное указание кодировки делает код самодокументируемым и устойчивым к изменениям окружения. UTF-8 является предпочтительной кодировкой для обмена данными в современных системах: она поддерживает все символы Unicode, эффективна для текстов на латинице и широко используется в вебе, JSON, XML.
Использование
#Java #советы
Тема:
String.getBytes() использует платформенно-зависимую кодировку.Проблема: Метод
String.getBytes() без аргументов преобразует строку в массив байт, используя системную кодировку по умолчанию, которая определяется операционной системой и настройками JVM (file.encoding). На разных платформах это может быть CP1251 (Windows), UTF-8 (Linux), MacRoman (macOS) или другие. Это приводит к тому, что одно и то же приложение на разных машинах генерирует разные байтовые последовательности для одинаковых строк, что вызывает ошибки при передаче данных по сети, записи в файлы или взаимодействии с внешними системами. Особенно критично для символов вне ASCII (кириллица, иероглифы) — они могут быть испорчены или потеряны. Даже если сейчас всё работает, при смене окружения (например, при деплое на сервер с другой кодировкой) приложение внезапно ломается, и диагностика затруднена, так как проблема проявляется только в определённых условиях.
Решение: Всегда указывайте кодировку явно с помощью
String.getBytes(Charset) или String.getBytes(String charsetName). Предпочтительно использовать константы из
StandardCharsets (Java 7+), например, StandardCharsets.UTF_8. Это гарантирует одинаковое поведение на всех платформах и делает намерения разработчика явными. Аналогичное правило применяется к конструктору new String(byte[], Charset) и другим методам преобразования между строками и байтами. Для проектов, ориентированных на международное взаимодействие, UTF-8 является стандартом де-факто.
import java.nio.charset.StandardCharsets;
import java.io.UnsupportedEncodingException;
public class StringGetBytes {
public static void main(String[] args) throws UnsupportedEncodingException {
String text = "Привет, мир!";
//Антипаттерн: платформенно-зависимая кодировка
byte[] badBytes = text.getBytes();
System.out.println("Длина (default): " + badBytes.length);
// На Windows (CP1251) результат может быть другим, чем на Linux (UTF-8)
//Решение: явная кодировка UTF-8
byte[] goodBytes = text.getBytes(StandardCharsets.UTF_8);
System.out.println("Длина (UTF-8): " + goodBytes.length);
// Также при обратном преобразовании
String restored = new String(goodBytes, StandardCharsets.UTF_8);
System.out.println("Восстановлено: " + restored);
// Для старых версий Java (до 7) используйте строковое имя
// byte[] bytes = text.getBytes("UTF-8");
// Но StandardCharsets предпочтительнее (типобезопасно)
// Демонстрация различий: символы вне ASCII кодируются по-разному
String euro = "€"; // Символ евро
byte[] utf8 = euro.getBytes(StandardCharsets.UTF_8); // 3 байта (E2 82 AC)
byte[] win1251 = euro.getBytes("Windows-1251"); // 1 байт (80) или не поддерживается
System.out.println("UTF-8 length: " + utf8.length);
System.out.println("Windows-1251 length: " + win1251.length);
}
}
Объяснение: Кодировка по умолчанию определяется системным свойством
file.encoding и может быть изменена при запуске JVM (например, -Dfile.encoding=UTF-8). Однако это глобальная настройка, которая может быть неочевидна для других разработчиков, а её изменение может повлиять на другие части системы (например, чтение файлов). Явное указание кодировки делает код самодокументируемым и устойчивым к изменениям окружения. UTF-8 является предпочтительной кодировкой для обмена данными в современных системах: она поддерживает все символы Unicode, эффективна для текстов на латинице и широко используется в вебе, JSON, XML.
Использование
StandardCharsets.UTF_8 исключает проверяемое исключение UnsupportedEncodingException, так как UTF-8 гарантированно поддерживается всеми реализациями JVM.#Java #советы
👍5
Что выведет код?
#Tasks
public class Task220726 {
public static void main(String[] args) {
String s = "é";
System.out.println(s.getBytes().length);
}
}#Tasks
👍2
👍2
Что такое 🤓
Ответ:
ForkJoinPool.commonPool() — это общий пул потоков для приложения (Java 8), используемый по умолчанию в параллельных стримах (parallelStream()) и CompletableFuture (в некоторых методах).
Размер по умолчанию = количество процессоров − 1.
Не рекомендуется блокировать (спать, ввод-вывод) внутри задач, выполняющихся в commonPool, так как это замедлит другие задачи.
Если ваши задачи могут блокироваться, создавайте отдельный ForkJoinPool. Используйте commonPool для коротких вычислительных задач, не блокирующих IO.
#собеседование
ForkJoinPool.commonPool() и когда его использовать? Ответ:
Размер по умолчанию = количество процессоров − 1.
Не рекомендуется блокировать (спать, ввод-вывод) внутри задач, выполняющихся в commonPool, так как это замедлит другие задачи.
Если ваши задачи могут блокироваться, создавайте отдельный ForkJoinPool. Используйте commonPool для коротких вычислительных задач, не блокирующих IO.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
История технологии сегодня — 23 июля
ℹ️ Кто родился в этот день
Влади́мир Я́ковлевич Кли́мов (1892—1962) — советский учёный в области авиационного моторостроения, конструктор авиационных двигателей, генерал-майор инженерно-авиационной службы (1944), академик АН СССР (1953). В ходе научных исследований и конструкторской работы Климовым были разработаны и внедрены специальная закрытая система жидкостного охлаждения поршневых авиационных двигателей под давлением, воздушный нагнетатель с двухскоростным приводом, усовершенствованная система газораспределения, система питания топливовоздушной смесью мощных и высокооборотных авиадвигателей, предложен ряд оригинальных решений в конструкциях ТРД. Климов внёс существенный вклад в развитие теории смазки, в решение проблем уравновешивания поршневых авиадвигателей и др. вопросов двигателестроения.
🌐 Знаковые события
1874 — Александр Николаевич Лодыгин получил привилегию № 1619 на лампу накаливания. Его изобретение было запатентовано и в нескольких европейских странах, Петербургская АН присудила ему в этом году Ломоносовскую премию, а в конце года было создано «Товарищество электрического освещения А. Н. Лодыгин и Ко».
1903 — спустя месяц после образования корпорации «Ford Motor Company» она выпустила в продажу свой первый автомобиль «модель А». В течение первого года своего существования компания произвела 1700 автомобилей. Первый автомобиль, выставленный на продажу, был описан как «наиболее совершенная машина на рынке, которую в состоянии водить даже 15-летний мальчик». Первый автомобиль был продан доктору Е. Пфеннингу (англ. Ernst Pfenning) из Чикаго, который купил машину месяц спустя после регистрации компании, к большой радости обеспокоенных акционеров, нервно наблюдавших за уменьшением банковского баланса до $223.
1980 — запуск космического корабля Союз-37, в составе его экипажа в космос отправился первый космонавт из Азии, вьетнамец Фам Туан (Phạm Tuân).
2015 — с помощью телескопа «Кеплер» найдена первая экзопланета земного типа, которая находится в зоне обитаемости солнцеподобной звезды — Kepler-452 b.
#Biography #Birth_Date #Events #23июля
Влади́мир Я́ковлевич Кли́мов (1892—1962) — советский учёный в области авиационного моторостроения, конструктор авиационных двигателей, генерал-майор инженерно-авиационной службы (1944), академик АН СССР (1953). В ходе научных исследований и конструкторской работы Климовым были разработаны и внедрены специальная закрытая система жидкостного охлаждения поршневых авиационных двигателей под давлением, воздушный нагнетатель с двухскоростным приводом, усовершенствованная система газораспределения, система питания топливовоздушной смесью мощных и высокооборотных авиадвигателей, предложен ряд оригинальных решений в конструкциях ТРД. Климов внёс существенный вклад в развитие теории смазки, в решение проблем уравновешивания поршневых авиадвигателей и др. вопросов двигателестроения.
1874 — Александр Николаевич Лодыгин получил привилегию № 1619 на лампу накаливания. Его изобретение было запатентовано и в нескольких европейских странах, Петербургская АН присудила ему в этом году Ломоносовскую премию, а в конце года было создано «Товарищество электрического освещения А. Н. Лодыгин и Ко».
1903 — спустя месяц после образования корпорации «Ford Motor Company» она выпустила в продажу свой первый автомобиль «модель А». В течение первого года своего существования компания произвела 1700 автомобилей. Первый автомобиль, выставленный на продажу, был описан как «наиболее совершенная машина на рынке, которую в состоянии водить даже 15-летний мальчик». Первый автомобиль был продан доктору Е. Пфеннингу (англ. Ernst Pfenning) из Чикаго, который купил машину месяц спустя после регистрации компании, к большой радости обеспокоенных акционеров, нервно наблюдавших за уменьшением банковского баланса до $223.
1980 — запуск космического корабля Союз-37, в составе его экипажа в космос отправился первый космонавт из Азии, вьетнамец Фам Туан (Phạm Tuân).
2015 — с помощью телескопа «Кеплер» найдена первая экзопланета земного типа, которая находится в зоне обитаемости солнцеподобной звезды — Kepler-452 b.
#Biography #Birth_Date #Events #23июля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Раздел 11. Работа с файлами, I/O и сетью (NIO.2)
Глава 2. Современный NIO.2 (java.nio.file)
Files.lines() и WatchService — построчное чтение и мониторинг файловой системы
Два механизма в Java NIO.2 решают противоположные задачи:
Files.lines(Path) — построчное чтение текстовых файлов
Метод
Важно:
BufferedReader — это класс в Java, который буферизует чтение символов из потока. Вместо чтения по одному символу или байту он читает блоками (обычно 8 КБ) в буфер в памяти, а затем отдаёт символы из буфера. Это снижает количество системных вызовов read() с O(N) до O(N / buffer_size).
Files.lines(Path, Charset) — с указанием кодировки
Если кодировка не указана, используется
Кодировка (charset, character encoding) — это схема сопоставления байтовых последовательностей символам текста. UTF-8 — переменная длина (1–4 байта на символ), обратно совместима с ASCII. ISO-8859-1 (Latin-1) — фиксированная 1 байт на символ, покрывает западноевропейские языки.
Ленивость и потребление памяти
В отличие от
WatchService — отслеживание изменений в файловой системе
WatchService — это сервис в NIO.2, который использует нативные механизмы ОС для мониторинга изменений в файловой системе. Вместо периодического опроса (polling) он работает по событийной модели: ОС уведомляет JVM, когда происходит зарегистрированное событие.
Polling (опрос) — это стратегия проверки состояния, при которой программа периодически запрашивает ресурс (например, проверяет время модификации файла). Это расходует CPU впустую. Событийная модель (event-driven) — противоположный подход, при котором программа ждёт уведомления от ОС и не потребляет ресурсы в ожидании.
Нативные механизмы ОС
WatchService в Java — это тонкая обёртка над нативными API:
Linux:
macOS:
Windows:
Важно:
Coalescing (слияние событий) — это оптимизация, при которой несколько последовательных событий над одним и тем же файлом объединяются в одно. Например, множественные быстрые записи в файл могут породить только одно событие ENTRY_MODIFY.
Создание WatchService
Регистрация директории
WatchKey — это объект, представляющий регистрацию директории в WatchService. Он содержит ссылку на зарегистрированный путь и очередь событий. Когда WatchKey становится недействительным (например, директория удалена), его метод isValid() возвращает false.
#Java #для_новичков #beginner #IO #NIO #Files #Files_lines #WatchService
Глава 2. Современный NIO.2 (java.nio.file)
Files.lines() и WatchService — построчное чтение и мониторинг файловой системы
Два механизма в Java NIO.2 решают противоположные задачи:
Files.lines() читает содержимое файла построчно, а WatchService наблюдает за изменениями в файловой системе без активного чтения. Первый экономит память при обработке больших текстовых файлов, второй — CPU при ожидании событий. Оба требуют строгого управления ресурсами, так как работают с нативными дескрипторами ОС, невидимыми для GC.Files.lines(Path) — построчное чтение текстовых файлов
Метод
Files.lines(Path path) возвращает Stream<String>, который лениво читает файл построчно. Каждая строка декодируется из байтов файла в символы с использованием кодировки по умолчанию (StandardCharsets.UTF_8).import java.nio.file.*;
import java.io.IOException;
import java.util.stream.Stream;
public class LineReader {
public void readLines(Path file) throws IOException {
// Stream<String> — ленивое чтение, строки появляются по мере обхода
try (Stream<String> lines = Files.lines(file)) {
lines.forEach(line -> System.out.println(line));
}
// BufferedReader закрыт автоматически try-with-resources
}
}
Важно:
Files.lines() открывает BufferedReader под капотом, который держит файловый дескриптор открытым. Поток Stream<String> должен быть закрыт через try-with-resources или явный close(). Если поток не закрыт, дескриптор останется открытым даже после того, как Stream будет собран GC.BufferedReader — это класс в Java, который буферизует чтение символов из потока. Вместо чтения по одному символу или байту он читает блоками (обычно 8 КБ) в буфер в памяти, а затем отдаёт символы из буфера. Это снижает количество системных вызовов read() с O(N) до O(N / buffer_size).
Files.lines(Path, Charset) — с указанием кодировки
import java.nio.charset.StandardCharsets;
public void readWithEncoding(Path file) throws IOException {
// Явное указание кодировки — обязательно для файлов не в UTF-8
try (Stream<String> lines = Files.lines(file, StandardCharsets.ISO_8859_1)) {
lines.forEach(System.out::println);
}
}
Если кодировка не указана, используется
Charset.defaultCharset(), которая зависит от ОС и локали. На Linux обычно UTF-8, на Windows — Windows-1252 или CP1251. Неявное использование дефолтной кодировки — распространённый источник багов при переносе приложения между платформами.Кодировка (charset, character encoding) — это схема сопоставления байтовых последовательностей символам текста. UTF-8 — переменная длина (1–4 байта на символ), обратно совместима с ASCII. ISO-8859-1 (Latin-1) — фиксированная 1 байт на символ, покрывает западноевропейские языки.
Ленивость и потребление памяти
Files.lines() — ленивый поток. Строка читается из файла только когда терминальная операция запрашивает следующий элемент. Это позволяет обрабатывать файлы любого размера с константным потреблением памяти:public void processHugeFile(Path file) throws IOException {
try (Stream<String> lines = Files.lines(file)) {
// Фильтрация и подсчёт — каждая строка обрабатывается и отбрасывается
long errorCount = lines.filter(line -> line.contains("ERROR"))
.count();
System.out.println("Ошибок: " + errorCount);
// Память не зависит от размера файла — только от длины одной строки
}
}В отличие от
Files.readAllLines(), который загружает весь файл в List<String> (потенциально гигабайты в куче), Files.lines() держит в памяти только текущую строку и буфер BufferedReader (8 КБ).WatchService — отслеживание изменений в файловой системе
WatchService — это сервис в NIO.2, который использует нативные механизмы ОС для мониторинга изменений в файловой системе. Вместо периодического опроса (polling) он работает по событийной модели: ОС уведомляет JVM, когда происходит зарегистрированное событие.
Polling (опрос) — это стратегия проверки состояния, при которой программа периодически запрашивает ресурс (например, проверяет время модификации файла). Это расходует CPU впустую. Событийная модель (event-driven) — противоположный подход, при котором программа ждёт уведомления от ОС и не потребляет ресурсы в ожидании.
Нативные механизмы ОС
WatchService в Java — это тонкая обёртка над нативными API:
Linux:
inotify — система уведомлений о событиях файловой системы на уровне ядра. Каждый WatchService создаёт экземпляр inotify через системный вызов inotify_init().macOS:
FSEvents — фреймворк уведомлений о изменениях файловой системы. Работает на уровне всей ФС, а не отдельных директорий, что даёт другую семантику событий.Windows:
ReadDirectoryChangesW — WinAPI функция для асинхронного чтения изменений директории.Важно:
WatchService не гарантирует доставку всех событий и не гарантирует порядок. Некоторые события могут быть пропущены при высокой нагрузке, и события могут приходить пачками (coalescing).Coalescing (слияние событий) — это оптимизация, при которой несколько последовательных событий над одним и тем же файлом объединяются в одно. Например, множественные быстрые записи в файл могут породить только одно событие ENTRY_MODIFY.
Создание WatchService
import java.nio.file.*;
public class WatchServiceFactory {
public WatchService createWatchService() throws IOException {
// Получаем WatchService для файловой системы по умолчанию
WatchService watchService = FileSystems.getDefault().newWatchService();
return watchService;
}
}
FileSystems.getDefault().newWatchService() создаёт нативный дескриптор inotify (Linux), регистрирует callback в FSEvents (macOS) или создаёт объект ожидания ReadDirectoryChangesW (Windows). Этот дескриптор существует в нативной памяти вне кучи JVM.Регистрация директории
import java.nio.file.*;
public class DirectoryRegistrar {
public void registerDirectory(Path dir, WatchService watchService) throws IOException {
// Регистрируем директорию на отслеживание создания, удаления и модификации
WatchKey key = dir.register(watchService,
StandardWatchEventKinds.ENTRY_CREATE, // создание файла/директории
StandardWatchEventKinds.ENTRY_DELETE, // удаление
StandardWatchEventKinds.ENTRY_MODIFY // изменение содержимого или метаданных
);
// WatchKey — это токен, идентифицирующий зарегистрированную директорию
// Его можно использовать для отмены регистрации
System.out.println("Директория зарегистрирована: " + dir);
}
}
WatchKey — это объект, представляющий регистрацию директории в WatchService. Он содержит ссылку на зарегистрированный путь и очередь событий. Когда WatchKey становится недействительным (например, директория удалена), его метод isValid() возвращает false.
#Java #для_новичков #beginner #IO #NIO #Files #Files_lines #WatchService
👍5
Ожидание событий: take() vs poll()
Важно: после обработки событий необходимо вызвать
Обработка WatchEvent
Важные нюансы WatchService
Событие CREATE приходит до завершения записи: если процесс создаёт файл и медленно пишет в него,
Событие MODIFY может приходить многократно: одна логическая операция записи может породить серию событий
Символические ссылки: WatchService следует по символическим ссылкам при регистрации. Если зарегистрировать ссылку, события будут приходить для целевой директории.
Рекурсивный мониторинг: WatchService не мониторит поддиректории автоматически. Для рекурсивного мониторинга нужно обходить дерево и регистрировать каждую директорию отдельно, а при появлении новой директории (событие
OVERFLOW: при слишком быстром потоке событий внутренний буфер ОС может переполниться. В этом случае приходит событие
Путь байтов в памяти JVM при построчном чтении
Files.lines(): путь данных
При
Метод создаёт
При итерации по
Чтение байтов из файла через
Декодирование байтов в символы через
Поиск символа перевода строки (
Создание нового объекта
Объект
После обработки строки в терминальной операции (например,
При закрытии
Путь байтов при WatchService
При создании
При регистрации директории (
При вызове
Объекты
При закрытии
Важно:
#Java #для_новичков #beginner #IO #NIO #Files #Files_lines #WatchService
import java.nio.file.*;
import java.util.concurrent.TimeUnit;
public class EventPoller {
// Блокирующее ожидание: поток ждёт, пока не появится событие
public void blockingWait(WatchService watchService) throws InterruptedException {
// take() блокирует поток до появления события
// Прерывается только при InterruptedException или закрытии WatchService
WatchKey key = watchService.take();
processKey(key);
}
// Неблокирующая проверка: возвращает null, если событий нет
public void nonBlockingPoll(WatchService watchService) {
WatchKey key = watchService.poll();
if (key != null) {
processKey(key);
} else {
System.out.println("Нет новых событий");
}
}
// Ожидание с таймаутом
public void timedPoll(WatchService watchService) throws InterruptedException {
// Ждём 5 секунд, если событий нет — возвращаем null
WatchKey key = watchService.poll(5, TimeUnit.SECONDS);
if (key != null) {
processKey(key);
}
}
private void processKey(WatchKey key) {
for (WatchEvent<?> event : key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
Path fileName = (Path) event.context(); // имя файла, вызвавшего событие
System.out.println("Событие: " + kind.name() + " для " + fileName);
}
// Сбрасываем ключ, чтобы получать новые события
boolean valid = key.reset();
if (!valid) {
System.out.println("Ключ больше не валиден — директория удалена");
}
}
}
take() — блокирующий метод, который переводит поток в состояние WAITING. Поток не потребляет CPU в этом состоянии. ОС пробуждает поток, когда приходит событие inotify/FSEvents/ReadDirectoryChangesW.poll() — неблокирующий. Если событий нет, немедленно возвращает null. Полезен в циклах, где нужно делать другую работу между проверками.poll(timeout, TimeUnit) — блокирует на указанное время, затем возвращает null или WatchKey.Важно: после обработки событий необходимо вызвать
key.reset(). Это сбрасывает состояние ключа и позволяет WatchService снова наполнять его событиями. Если reset() не вызван, ключ перестаёт получать новые события. Если reset() возвращает false, ключ больше не валиден (обычно потому, что директория удалена).Обработка WatchEvent
WatchEvent<?> event = ...;
// Тип события: ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY
WatchEvent.Kind<?> kind = event.kind();
// Имя файла или директории, вызвавшей событие (относительно зарегистрированной директории)
Path context = (Path) event.context();
// Количество событий данного типа для этого файла (может быть > 1 при coalescing)
int count = event.count();
event.context() возвращает Path, но это не абсолютный путь — это имя файла относительно зарегистрированной директории. Для получения абсолютного пути нужно резолвить через watchable() ключа:Path dir = (Path) key.watchable(); // зарегистрированная директория
Path absolute = dir.resolve(context); // полный путь
Важные нюансы WatchService
Событие CREATE приходит до завершения записи: если процесс создаёт файл и медленно пишет в него,
ENTRY_CREATE приходит сразу после появления inode. Файл может быть ещё пустым или заблокирован на запись. Решение — ожидание готовности (как в waitForFileReady()) или использование временных имён с последующим атомарным переименованием.Событие MODIFY может приходить многократно: одна логическая операция записи может породить серию событий
ENTRY_MODIFY. Приложение должно быть готово к дедупликации или игнорированию промежуточных событий.Символические ссылки: WatchService следует по символическим ссылкам при регистрации. Если зарегистрировать ссылку, события будут приходить для целевой директории.
Рекурсивный мониторинг: WatchService не мониторит поддиректории автоматически. Для рекурсивного мониторинга нужно обходить дерево и регистрировать каждую директорию отдельно, а при появлении новой директории (событие
ENTRY_CREATE для директории) регистрировать её динамически.OVERFLOW: при слишком быстром потоке событий внутренний буфер ОС может переполниться. В этом случае приходит событие
OVERFLOW, и часть событий теряется. Приложение должно обрабатывать это как сигнал к полному пересканированию директории.Путь байтов в памяти JVM при построчном чтении
Files.lines(): путь данных
При
Files.lines(file):Метод создаёт
BufferedReader — объект в куче, который оборачивает InputStreamReader, который оборачивает FileInputStream. Каждый из этих объектов — в куче. FileInputStream содержит файловый дескриптор (целое число в нативной памяти).BufferedReader выделяет буфер char[] размером 8192 символов (по умолчанию) в Young Generation. Этот буфер переиспользуется для всех операций чтения.При итерации по
Stream<String> каждый вызов readLine() выполняет:Чтение байтов из файла через
FileInputStream.read() в буфер BufferedReader.Декодирование байтов в символы через
CharsetDecoder (для UTF-8 — переменная длина, 1–4 байта на символ).Поиск символа перевода строки (
\n, \r\n или \r).Создание нового объекта
String для строки.Объект
String создаётся в Young Generation (Eden). Если строка длинная (например, CSV-строка с тысячей символов), она может быть размещена сразу в Old Generation как humongous object (в G1 GC, если размер превышает половину региона).После обработки строки в терминальной операции (например,
count() или forEach()) ссылка на String исчезает. Объект становится мусором и собирается Minor GC. Буфер BufferedReader остаётся живым до закрытия потока.При закрытии
Stream (через try-with-resources) вызывается BufferedReader.close(), который закрывает FileInputStream, который выполняет системный вызов close() для освобождения файлового дескриптора. Если поток не закрыт, дескриптор утечёт.Путь байтов при WatchService
При создании
WatchService:FileSystems.getDefault().newWatchService() создаёт объект WatchService в куче. На Linux это обёртка над InotifyWatchService, который выполняет системный вызов inotify_init().inotify_init() создаёт экземпляр inotify в ядре Linux и возвращает файловый дескриптор. Этот дескриптор хранится в нативной памяти JVM, ассоциированной с объектом WatchService.При регистрации директории (
dir.register(...)) выполняется inotify_add_watch(), который добавляет "watch" (наблюдение) за директорией в ядре. Ядро начинает отслеживать события для этой директории и всех её прямых потомков.inotify в ядре использует собственный буфер событий (обычно 16 КБ по умолчанию, настраивается через /proc/sys/fs/inotify/max_queued_events). Если событий больше, чем вмещает буфер, приходит OVERFLOW.При вызове
watchService.take() поток Java блокируется на системном вызове read() от дескриптора inotify. Поток переводится в состояние WAITING — он не потребляет CPU. Когда событие появляется, ядро пробуждает поток, read() возвращает структуру события, и JVM создаёт объекты WatchKey и WatchEvent в куче.Объекты
WatchKey и WatchEvent создаются в Young Generation. WatchKey может переживать несколько циклов событий, если его не сбросить через reset(). WatchEvent — одноразовый объект, который становится мусором после обработки.При закрытии
WatchService (watchService.close()) выполняется inotify_rm_watch() для всех зарегистрированных наблюдений и close() для дескриптора inotify. Это освобождает ресурсы ядра. Если WatchService не закрыт, дескриптор inotify остаётся открытым до завершения процесса.Важно:
inotify на Linux не рекурсивен. WatchService регистрирует наблюдение только для указанной директории, не для поддиректорий. Для рекурсивного мониторинга Java обходит дерево и создаёт отдельный inotify_add_watch() для каждой директории. Каждый watch потребляет ресурсы ядра (inode наблюдения), и их количество ограничено (/proc/sys/fs/inotify/max_user_watches, обычно 8192).#Java #для_новичков #beginner #IO #NIO #Files #Files_lines #WatchService
👍4
Что выведет код?
#Tasks
import java.nio.file.*;
import java.util.*;
import java.util.stream.Stream;
public class FilesLinesTricky {
public static void main(String[] args) throws Exception {
Path file = Paths.get("test.txt");
Files.write(file, Arrays.asList("A", "B", "C"));
try (Stream<String> lines = Files.lines(file)) {
Iterator<String> it = lines.iterator();
System.out.print(it.next());
System.out.print(it.next());
Files.write(file, Arrays.asList("D", "E"), StandardOpenOption.APPEND);
while (it.hasNext()) {
System.out.print(it.next());
}
}
}
}
#Tasks
👍3
👍3
Media is too big
VIEW IN TELEGRAM
Небольшая демонстрация предрелизной логики Devforge.ru 🙈
Жду оценок и мнений!😏
пысы: схемы можно писать через язык Mermaid🤓
Жду оценок и мнений!
пысы: схемы можно писать через язык Mermaid
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥1
Что такое 🤓
Ответ:
ZGC (Java 11 как экспериментальный, стабилен с Java 15) — это низколатентный сборщик мусора, работающий с паузами менее 10 мс (в основном менее 1 мс), даже для терабайтных куч.
Использует механизм colored pointers и load barriers. Работает параллельно с приложением, не останавливая его для полной сборки (concurrent).
Не требует больших тюнингов. Подходит для приложений реального времени, микросервисов с низкими SLI по задержкам.
Альтернатива — Shenandoah (от Red Hat), похожий по идеологии.
#собеседование
ZGC (Z Garbage Collector)? Ответ:
Использует механизм colored pointers и load barriers. Работает параллельно с приложением, не останавливая его для полной сборки (concurrent).
Не требует больших тюнингов. Подходит для приложений реального времени, микросервисов с низкими SLI по задержкам.
Альтернатива — Shenandoah (от Red Hat), похожий по идеологии.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
История технологии сегодня — 24 июля
ℹ️ Кто родился в этот день
Шарль Эми́ль Пика́р (фр. Charles Émile Picard; 24 июля 1856, Париж — 11 декабря 1941, там же) — французский математик. Известен фундаментальными результатами в области математического анализа. Его учебник анализа (Traité d’Analyse) долгое время считался классическим. Внёс существенный вклад также в теорию дифференциальных уравнений, теорию функций, топологию, теорию групп. Для линейных дифференциальных уравнений разработал аналог теории Галуа. Часть его трудов посвящены истории и философии математики.
🌐 Знаковые события
1987 — IBM выпустила операционную систему DOS version 3.3.
#Biography #Birth_Date #Events #24июля
Шарль Эми́ль Пика́р (фр. Charles Émile Picard; 24 июля 1856, Париж — 11 декабря 1941, там же) — французский математик. Известен фундаментальными результатами в области математического анализа. Его учебник анализа (Traité d’Analyse) долгое время считался классическим. Внёс существенный вклад также в теорию дифференциальных уравнений, теорию функций, топологию, теорию групп. Для линейных дифференциальных уравнений разработал аналог теории Галуа. Часть его трудов посвящены истории и философии математики.
1987 — IBM выпустила операционную систему DOS version 3.3.
#Biography #Birth_Date #Events #24июля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
[Совет по Java #064]
Тема:
Проблема:
Это удобно для кэшей или метаданных, привязанных к объектам. Однако внутри
Решение: При использовании
Если архитектура требует, чтобы значение знало о ключе, следует хранить значение в виде
Альтернативно, можно использовать
Объяснение: В
Сборщик мусора определяет достижимость объектов: если от корней GC (например, статические поля, локальные переменные) нет цепочки сильных ссылок к ключу, ключ считается слабодостижимым. Однако если значение содержит сильную ссылку на ключ, то цепочка
Таким образом, ключ не является слабодостижимым, и запись не удаляется. Это классический случай утечки памяти, который трудно диагностировать, потому что
#Java #советы
Тема:
WeakHashMap хранит ключи через слабые ссылки, но значения — сильные. Значение может удерживать ключ, предотвращая удаление.Проблема:
WeakHashMap предназначена для хранения записей, ключи которых могут быть собраны сборщиком мусора (GC), если на них нет сильных ссылок. Это удобно для кэшей или метаданных, привязанных к объектам. Однако внутри
WeakHashMap значения хранятся через сильные ссылки (обычные ссылки). Если значение содержит ссылку на свой ключ (прямо или косвенно), то образуется цикл: ключ держит значение через map, а значение держит ключ через свою ссылку. В результате ни ключ, ни значение не становятся достижимыми только через слабую ссылку, и запись никогда не удаляется из WeakHashMap. Это приводит к утечке памяти, так как объекты остаются живыми, несмотря на то, что внешние ссылки на ключ отсутствуют. Разработчики часто не учитывают этот нюанс и используют WeakHashMap для кэширования, полагая, что оно автоматически очищается, а затем сталкиваются с неожиданным ростом памяти.Решение: При использовании
WeakHashMap необходимо гарантировать, что значение не содержит ссылки на ключ. Если архитектура требует, чтобы значение знало о ключе, следует хранить значение в виде
WeakReference или использовать отдельную структуру. Альтернативно, можно использовать
WeakHashMap только для простых типов ключей (например, строк), которые не хранятся в значениях. Для сложных кэшей лучше применять библиотеки типа Caffeine или Guava Cache, которые предоставляют более гибкие стратегии очистки и не страдают от этой проблемы. В случае, если значение обязательно должно ссылаться на ключ, можно использовать java.lang.ref.WeakReference для значения и хранить его в WeakHashMap, но тогда нужно самостоятельно обрабатывать удаление.import java.util.WeakHashMap;
import java.lang.ref.WeakReference;
public class WeakHashMapPitfall {
static class Key { /* ... */ }
static class Value {
private final Key key; // ссылка на ключ!
Value(Key key) { this.key = key; }
}
public static void main(String[] args) {
//Антипаттерн: значение ссылается на ключ
WeakHashMap<Key, Value> map = new WeakHashMap<>();
Key key = new Key();
map.put(key, new Value(key)); // значение хранит ссылку на ключ
key = null; // убираем внешнюю ссылку
System.gc(); // попытка сборки
// Запись не будет удалена, так как Value держит Key
System.out.println("Size: " + map.size()); // 1 — утечка!
//Решение: не хранить ссылку на ключ в значении
static class SafeValue {
// без ссылки на Key
}
WeakHashMap<Key, SafeValue> safeMap = new WeakHashMap<>();
Key key2 = new Key();
safeMap.put(key2, new SafeValue());
key2 = null;
System.gc();
// Запись будет удалена
System.out.println("Safe size: " + safeMap.size()); // 0
// Альтернатива: использовать WeakReference для значения
WeakHashMap<Key, WeakReference<Value>> refMap = new WeakHashMap<>();
Key key3 = new Key();
refMap.put(key3, new WeakReference<>(new Value(key3))); // всё равно Value ссылается на Key
// это не решает проблему, если Value ссылается на Key
}
}
Объяснение: В
WeakHashMap запись удаляется, когда ключ становится доступным только через слабую ссылку (т.е. нет сильных ссылок на ключ, кроме самой карты). Сборщик мусора определяет достижимость объектов: если от корней GC (например, статические поля, локальные переменные) нет цепочки сильных ссылок к ключу, ключ считается слабодостижимым. Однако если значение содержит сильную ссылку на ключ, то цепочка
map -> значение -> ключ создает сильную достижимость ключа (через значение). Таким образом, ключ не является слабодостижимым, и запись не удаляется. Это классический случай утечки памяти, который трудно диагностировать, потому что
WeakHashMap работает как ожидается для большинства случаев. #Java #советы
👍3
Что выведет код?
#Tasks
public class Task240726 {
static class Key {
String id;
Key(String id) { this.id = id; }
@Override
public int hashCode() { return id.hashCode(); }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Key)) return false;
Key key = (Key) o;
return id.equals(key.id);
}
}
static class Value {
Key ref;
Value(Key ref) { this.ref = ref; }
}
public static void main(String[] args) throws InterruptedException {
WeakHashMap<Key, Value> map = new WeakHashMap<>();
Key key1 = new Key("one");
Key key2 = new Key("two");
map.put(key1, new Value(key1));
map.put(key2, new Value(null));
key1 = null;
key2 = null;
System.gc();
Thread.sleep(1000);
System.out.println(map.size());
System.out.println(map.containsKey(new Key("one")));
System.out.println(map.containsKey(new Key("two")));
}
}#Tasks
👍2
👍2
Что такое 🤓
Ответ:
Начиная с Java 17 (preview с Java 17, финал в Java 21), switch может сопоставлять не только константы, но и типы объектов с автоматическим приведением.
Пример:
String result = switch (obj)
{
case Integer i -> "Integer: " + i;
case String s -> "String: " + s;
case null -> "null"; default -> "Unknown";
};.
Также поддерживаются охранные условия (guards): case Point p when p.x() > 0 -> ....
Это делает switch полноценным инструментом для работы с иерархиями типов, уменьшая количество instanceof и приведений.
#собеседование
switch с паттернами (Pattern Matching for Switch)? Ответ:
Пример:
String result = switch (obj)
{
case Integer i -> "Integer: " + i;
case String s -> "String: " + s;
case null -> "null"; default -> "Unknown";
};.
Также поддерживаются охранные условия (guards): case Point p when p.x() > 0 -> ....
Это делает switch полноценным инструментом для работы с иерархиями типов, уменьшая количество instanceof и приведений.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
История технологии сегодня — 25 июля
ℹ️ Кто родился в этот день
Джон Баннистер Гуденаф (англ. John Bannister Goodenough; 25 июля 1922, Йена, Тюрингия[вд] — 25 июня 2023, Остин) — американский учёный, специалист в области физики и химии твёрдого тела и материаловедения. Известен своим вкладом в разработку первых литий-ионных аккумуляторов.
🌐 Знаковые события
1907 — русский физик Борис Розинг подал заявку на патент на «Способ электрической передачи изображений на расстояние», то есть телевидение.
#Biography #Birth_Date #Events #25июля
Джон Баннистер Гуденаф (англ. John Bannister Goodenough; 25 июля 1922, Йена, Тюрингия[вд] — 25 июня 2023, Остин) — американский учёный, специалист в области физики и химии твёрдого тела и материаловедения. Известен своим вкладом в разработку первых литий-ионных аккумуляторов.
1907 — русский физик Борис Розинг подал заявку на патент на «Способ электрической передачи изображений на расстояние», то есть телевидение.
#Biography #Birth_Date #Events #25июля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
История технологии сегодня — 26 июля
ℹ️ Кто родился в этот день
Джеймс Эфрэйм Лавлок (англ. James Ephraim Lovelock; 26 июля 1919, Летчуэрт, Хартфордшир — 26 июля 2022[3], Эбботсбери[вд], Юго-Западная Англия) — британский учёный, независимый исследователь, биофизик, химик, футуролог. Приобрёл известность как создатель Гипотезы Геи (согласно которой планета Земля функционирует как суперорганизм), а также как активный сторонник использования атомной энергии.
Исаак Бэббитт (англ. Isaac Babbitt; 26 июля 1799, Тонтон, Массачусетс, США — 26 мая 1862, Сомервилл, Массачусетс, США) — американский изобретатель. В 1839 году он изобрел подшипник из металлического сплава на основе олова с низким коэффициентом трения. Этот металл был назван по его имени баббитом, и до сих пор широко используется в подшипниках.
🌐 Знаковые события
1925 — впервые поднялся в воздух самолёт «К-1» конструкции К. А. Калинина — первый отечественный пассажирский самолёт, рекомендованный к серийному выпуску.
1989 — 24-летнему американскому студенту Роберту Моррису предъявляется обвинение в создании и запуске компьютерного вируса. Моррис становится первым создателем вируса, подвергнутым уголовному преследованию.
#Biography #Birth_Date #Events #26июля
Джеймс Эфрэйм Лавлок (англ. James Ephraim Lovelock; 26 июля 1919, Летчуэрт, Хартфордшир — 26 июля 2022[3], Эбботсбери[вд], Юго-Западная Англия) — британский учёный, независимый исследователь, биофизик, химик, футуролог. Приобрёл известность как создатель Гипотезы Геи (согласно которой планета Земля функционирует как суперорганизм), а также как активный сторонник использования атомной энергии.
Исаак Бэббитт (англ. Isaac Babbitt; 26 июля 1799, Тонтон, Массачусетс, США — 26 мая 1862, Сомервилл, Массачусетс, США) — американский изобретатель. В 1839 году он изобрел подшипник из металлического сплава на основе олова с низким коэффициентом трения. Этот металл был назван по его имени баббитом, и до сих пор широко используется в подшипниках.
1925 — впервые поднялся в воздух самолёт «К-1» конструкции К. А. Калинина — первый отечественный пассажирский самолёт, рекомендованный к серийному выпуску.
1989 — 24-летнему американскому студенту Роберту Моррису предъявляется обвинение в создании и запуске компьютерного вируса. Моррис становится первым создателем вируса, подвергнутым уголовному преследованию.
#Biography #Birth_Date #Events #26июля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2