👍2
Что такое NavigableMap и NavigableSet?🤓
Ответ:
NavigableMap (реализация — TreeMap) и NavigableSet (TreeSet) расширяют SortedMap/SortedSet, добавляя методы для навигации, близкие к запросам "ближайший меньший/больший элемент".
Полезные методы:
lowerKey() / lowerEntry() (строго меньше),
floorKey() (меньше или равно),
ceilingKey() (больше или равно),
higherKey() (строго больше),
descendingMap() (обратный порядок),
subMap(from, to) (диапазон с опциями включения границ).
Удобно для поиска интервалов, например, в системах бронирования.
#собеседование
Ответ:
NavigableMap (реализация — TreeMap)
Полезные методы:
lowerKey() / lowerEntry() (строго меньше),
floorKey() (меньше или равно),
ceilingKey() (больше или равно),
higherKey() (строго больше),
descendingMap() (обратный порядок),
subMap(from, to) (диапазон с опциями включения границ).
Удобно для поиска интервалов, например, в системах бронирования.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Всем доброго летнего утра! 👋
Вот вывел своего конька погулять, впервые в этом году 🚲
Че нам безработным🤣🤣🤣
А как ваше утро проходит?
Вот вывел своего конька погулять, впервые в этом году 🚲
Че нам безработным🤣🤣🤣
А как ваше утро проходит?
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4👍2
История технологии сегодня — 3 июня
ℹ️ Кто родился в этот день
И́горь Ростисла́вович Шафаре́вич (3 июня 1923, Житомир — 19 февраля 2017, Москва) — советский и российский математик, доктор физико-математических наук, профессор, академик Российской академии наук (1991; член-корреспондент Академии наук СССР с 1958). Основные труды посвящены алгебре, теории чисел и алгебраической геометрии.
Дьёрдь фон Бе́кеши (Джордж) (венг. Békésy György; нем. Georg von Békésy; 3 июня 1899, Будапешт — 13 июня 1972, Гонолулу, Гавайи, США) — венгерско-американский физик, биофизик и физиолог, лауреат Нобелевской премии в области медицины 1961 года. Основные труды по биофизике и физиологии слуха. Открыл закономерности колебаний базилярной мембраны улитки внутреннего уха при действии звука и сформулировал теорию первичного амплитудно-частотного анализа звуков в органе слуха. Изучал передачу звука в среднем ухе. Предложил метод и прибор оценки слуха человека, порога различения слуха (аудиометр Бекеши). Исследования по костной проводимости звука, пространственному слуху и контрасту восприятия в сенсорных системах.
🌐 Знаковые события
1980 — вследствие сбоя компьютера, сообщившего о советском ядерном нападении, в США объявлена ядерная тревога. В течение десяти минут мир находился на краю ядерной войны.
#Biography #Birth_Date #Events #03июня
И́горь Ростисла́вович Шафаре́вич (3 июня 1923, Житомир — 19 февраля 2017, Москва) — советский и российский математик, доктор физико-математических наук, профессор, академик Российской академии наук (1991; член-корреспондент Академии наук СССР с 1958). Основные труды посвящены алгебре, теории чисел и алгебраической геометрии.
Дьёрдь фон Бе́кеши (Джордж) (венг. Békésy György; нем. Georg von Békésy; 3 июня 1899, Будапешт — 13 июня 1972, Гонолулу, Гавайи, США) — венгерско-американский физик, биофизик и физиолог, лауреат Нобелевской премии в области медицины 1961 года. Основные труды по биофизике и физиологии слуха. Открыл закономерности колебаний базилярной мембраны улитки внутреннего уха при действии звука и сформулировал теорию первичного амплитудно-частотного анализа звуков в органе слуха. Изучал передачу звука в среднем ухе. Предложил метод и прибор оценки слуха человека, порога различения слуха (аудиометр Бекеши). Исследования по костной проводимости звука, пространственному слуху и контрасту восприятия в сенсорных системах.
1980 — вследствие сбоя компьютера, сообщившего о советском ядерном нападении, в США объявлена ядерная тревога. В течение десяти минут мир находился на краю ядерной войны.
#Biography #Birth_Date #Events #03июня
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Раздел 11. Работа с файлами, I/O и сетью (NIO.2)
Глава 1. Классический Java I/O (java.io)
FileInputStream – чтение байтов из файла. Путь данных в памяти JVM
В отличие от
Конструкторы и жизненный цикл файлового дескриптора
Оба конструктора выполняют одну и ту же последовательность операций на уровне JVM и ОС:
Валидация параметра. Проверка на null, проверка существования файла через системный вызов
Открытие файла. Системный вызов
Создание объекта
Файловый дескриптор — это ограниченный ресурс операционной системы. Каждый процесс имеет лимит на количество открытых дескрипторов (обычно 1024 по умолчанию, расширяемый до миллионов через
FileNotFoundException: семантика и обработка
Конструкторы
Это исключение возникает в трех основных сценариях:
Файл не существует по указанному пути
Файл существует, но является директорией, а не обычным файлом
Файл существует, но приложение не имеет прав на чтение
#Java #для_новичков #beginner #IO #NIO #FileInputStream
Глава 1. Классический Java I/O (java.io)
FileInputStream – чтение байтов из файла. Путь данных в памяти JVM
FileInputStream — конкретная реализация InputStream, предназначенная для чтения байтов из файловой системы. Она представляет собой низкоуровневый мост между Java-кодом и операционной системой: каждый вызов read() транслируется в системный вызов read() ядра ОС, который взаимодействует с файловой системой и блочным устройством хранения.В отличие от
BufferedInputStream, FileInputStream не выполняет внутреннюю буферизацию. Каждый вызов read() напрямую обращается к ОС, что делает посимвольное чтение через FileInputStream крайне неэффективным для больших файлов. Однако именно эта прямота делает FileInputStream полезным для сценариев, где требуется точный контроль над каждым системным вызовом: чтение с устройств с поблочным доступом, работа с pipe-файлами, или как underlying поток для буферизующих оберток.Конструкторы и жизненный цикл файлового дескриптора
FileInputStream предоставляет два основных конструктора:// Конструктор по строковому пути
public FileInputStream(String name) throws FileNotFoundException
// Конструктор по объекту File
public FileInputStream(File file) throws FileNotFoundException
Оба конструктора выполняют одну и ту же последовательность операций на уровне JVM и ОС:
Валидация параметра. Проверка на null, проверка существования файла через системный вызов
stat() или аналог.Открытие файла. Системный вызов
open() создает файловый дескриптор (file descriptor) — целочисленный идентификатор, представляющий открытый файл в контексте процесса.Создание объекта
FileInputStream. Выделение объекта в heap JVM, инициализация полей, включая нативное поле fd типа FileDescriptor, которое хранит целочисленный дескриптор ОС.Файловый дескриптор — это ограниченный ресурс операционной системы. Каждый процесс имеет лимит на количество открытых дескрипторов (обычно 1024 по умолчанию, расширяемый до миллионов через
ulimit). Незакрытый FileInputStream удерживает дескриптор до вызова close() или финализации объекта GC, что создает риск исчерпания лимита при интенсивном открытии файлов без закрытия.FileNotFoundException: семантика и обработка
Конструкторы
FileInputStream объявляют throws FileNotFoundException — checked-исключение, которое компилятор обязывает обрабатывать. Это исключение возникает в трех основных сценариях:
Файл не существует по указанному пути
Файл существует, но является директорией, а не обычным файлом
Файл существует, но приложение не имеет прав на чтение
public byte[] readFileContent(String path) {
try (FileInputStream fis = new FileInputStream(path)) {
return fis.readAllBytes();
} catch (FileNotFoundException e) {
// Файл не существует или недоступен — бизнес-решение
logger.warn("File not found: {}", path);
return new byte[0];
} catch (IOException e) {
// Другие I/O ошибки при чтении
logger.error("Failed to read file: {}", path, e);
throw new RuntimeException("File read error", e);
}
}FileNotFoundException наследует IOException и является восстановимым сбоем в контексте файловых операций. Приложение может предпринять альтернативные действия: использовать значение по умолчанию, создать файл, запросить другой путь. В отличие от RuntimeException, checked-природа FileNotFoundException форсирует явную обработку в коде.#Java #для_новичков #beginner #IO #NIO #FileInputStream
👍4
Путь данных от диска до heap JVM
Уровень 1: Физическое чтение с носителя
Данные хранятся на блочном устройстве — SSD, HDD, NVMe — в секторах фиксированного размера (обычно 512 байт или 4KB). Когда ОС запрашивает чтение файла, драйвер устройства транслирует логические блоки файловой системы в физические адреса секторов. Для SSD контроллер выполняет wear leveling и garbage collection на уровне флеш-памяти, независимо от JVM.
Уровень 2: Страничный кэш ядра (Page Cache)
Операционная система поддерживает страничный кэш — область оперативной памяти ядра, где хранятся недавно прочитанные страницы файлов. Размер страницы обычно 4KB. При первом чтении файла данные загружаются с диска в page cache. При повторном чтении тех же данных ОС возвращает их из page cache без обращения к диску.
Page cache — это память ядра, недоступная напрямую из Java. JVM не управляет этой памятью и не видит её в heap. Однако интенсивное чтение больших файлов вытесняет другие страницы из кэша, что может повлиять на производительность всей системы.
Уровень 3: Системный вызов и нативный буфер
Когда
Нативный метод
Уровень 4: Копирование в heap JVM
После выполнения системного вызова данные копируются из нативного буфера в массив
Для
Пример: посимвольное чтение и нагрузка на память
В этом коде каждый вызов
С точки зрения памяти:
Объект
Локальная переменная
Никаких массивов в heap не создается при каждом вызове
Проблема не в GC, а в количестве системных вызовов
Однако при выводе в
#Java #для_новичков #beginner #IO #NIO #FileInputStream
Уровень 1: Физическое чтение с носителя
Данные хранятся на блочном устройстве — SSD, HDD, NVMe — в секторах фиксированного размера (обычно 512 байт или 4KB). Когда ОС запрашивает чтение файла, драйвер устройства транслирует логические блоки файловой системы в физические адреса секторов. Для SSD контроллер выполняет wear leveling и garbage collection на уровне флеш-памяти, независимо от JVM.
Уровень 2: Страничный кэш ядра (Page Cache)
Операционная система поддерживает страничный кэш — область оперативной памяти ядра, где хранятся недавно прочитанные страницы файлов. Размер страницы обычно 4KB. При первом чтении файла данные загружаются с диска в page cache. При повторном чтении тех же данных ОС возвращает их из page cache без обращения к диску.
Page cache — это память ядра, недоступная напрямую из Java. JVM не управляет этой памятью и не видит её в heap. Однако интенсивное чтение больших файлов вытесняет другие страницы из кэша, что может повлиять на производительность всей системы.
Уровень 3: Системный вызов и нативный буфер
Когда
FileInputStream.read() вызывается, JVM выполняет системный вызов read() через JNI (Java Native Interface). Ядро ОС копирует данные из page cache в нативный буфер в userspace — память процесса JVM за пределами heap. Это первое копирование данных.// read() вызывает нативный метод, который выполняет системный вызов
public native int read() throws IOException;
Нативный метод
read0() в FileInputStream.c из OpenJDK вызывает IO_Read на POSIX-системах, который оборачивает read(fd, buf, 1) для посимвольного чтения или read(fd, buf, len) для буферизованного.Уровень 4: Копирование в heap JVM
После выполнения системного вызова данные копируются из нативного буфера в массив
byte[] в heap JVM. Это второе копирование. Только после этого данные становятся доступны Java-коду.// Путь данных для read():
// 1. Диск -> page cache (ядро)
// 2. page cache -> нативный буфер (userspace, вне heap)
// 3. нативный буфер -> byte[] в heap JVM
// 4. Java-код читает byte[0]
Для
read(byte[] b) путь аналогичен, но шаг 3 копирует до b.length байт за одну операцию.Пример: посимвольное чтение и нагрузка на память
public void readByteByByte(String path) throws IOException {
try (FileInputStream fis = new FileInputStream(path)) {
int byteValue;
// Каждая итерация: системный вызов + копирование в heap для 1 байта
while ((byteValue = fis.read()) != -1) {
System.out.printf("%02X ", byteValue);
}
}
}В этом коде каждый вызов
read() порождает полный путь данных для одного байта. С точки зрения памяти:
Объект
FileInputStream создается в heap и живет до выхода из tryЛокальная переменная
byteValue хранится в стеке потокаНикаких массивов в heap не создается при каждом вызове
Проблема не в GC, а в количестве системных вызовов
Однако при выводе в
System.out каждый вызов printf создает объекты String и StringBuilder в heap для форматирования, что нагружает GC при больших файлах.#Java #для_новичков #beginner #IO #NIO #FileInputStream
👍4
Буферизация и сокращение пути данных
Путь данных с BufferedInputStream:
Первый
Второй
После исчерпания
Массив
Роль garbage collector
Жизненный цикл объектов I/O
Важно:
В этом случае при исключении между
Финализация и Cleaner
В современных версиях Java
#Java #для_новичков #beginner #IO #NIO #FileInputStream
BufferedInputStream добавляет промежуточный массив в heap, сокращая количество системных вызовов:public void readBuffered(String path) throws IOException {
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(path))) {
int byteValue;
// Первый read(): чтение 8192 байт в buf[8192] одним системным вызовом
// Последующие read(): возврат из buf без системных вызовов
while ((byteValue = bis.read()) != -1) {
System.out.printf("%02X ", byteValue);
}
}
}Путь данных с BufferedInputStream:
Первый
read(): диск -> page cache -> нативный буфер -> buf[8192] в heap -> возврат buf[0]Второй
read(): buf[1] из heap (системный вызов отсутствует, нативный буфер не задействован)После исчерпания
buf: повторение шага 1Массив
buf создается при конструировании BufferedInputStream и живет до закрытия потока. GC не вовлечен в работу цикла чтения, так как массив переиспользуется.Роль garbage collector
Жизненный цикл объектов I/O
try (FileInputStream fis = new FileInputStream(path)) {
// fis — ссылка в стеке, объект FileInputStream в heap
// fis.fd — объект FileDescriptor в heap, хранит int fd (файловый дескриптор ОС)
// При использовании BufferedInputStream: bis.buf — byte[] в heap
}
// После выхода из try:
// 1. Вызывается fis.close() — закрывается файловый дескриптор ОС
// 2. Ссылка fis выходит из области видимости
// 3. Объект FileInputStream становится недостижимым
// 4. GC может собрать объект и связанные FileDescriptor при следующей сборкеВажно:
FileInputStream реализует AutoCloseable, и try-with-resources гарантирует вызов close(). Если бы мы использовали старый подход без try-with-resources:// Антипаттерн: утечка файлового дескриптора
FileInputStream fis = new FileInputStream(path);
// Если здесь возникнет исключение, close() не вызовется
fis.read();
fis.close();
В этом случае при исключении между
read() и close() файловый дескриптор остается открытым. Объект FileInputStream все еще достижим через локальную переменную до выхода из метода, но если исключение пробрасывается наверх, метод завершается без закрытия. GC финализирует объект и закроет дескриптор, но финализация непредсказуема по времени — может пройти секунды или минуты до освобождения ресурса.Финализация и Cleaner
В современных версиях Java
FileInputStream использует java.lang.ref.Cleaner вместо устаревшего метода finalize(). Cleaner регистрирует cleanup-действие, которое выполняется, когда объект становится фантомно достижимым (phantom reachable) — то есть недостижимым, но еще не собранным GC.// Упрощенная логика из OpenJDK
private final Cleanable cleanable;
private final FileCleanable cleanup;
public FileInputStream(File file) throws FileNotFoundException {
// ...
this.fd = new FileDescriptor();
this.cleanup = new FileCleanable(this.fd);
this.cleanable = Cleaner.create().register(this, cleanup);
}
FileCleanable — это Runnable, который вызывает close0(fd) — нативный метод закрытия дескриптора. Этот механизм гарантирует освобождение ресурса даже при забывчивости разработчика, но не заменяет явный вызов close(): Cleaner работает в отдельном потоке с низким приоритетом, и задержка может быть значительной.#Java #для_новичков #beginner #IO #NIO #FileInputStream
👍4
Что выведет код?
#Tasks
import java.io.*;
public class Task030626 {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("missing.txt")) {
System.out.println("Opened");
} catch (IOException e) {
System.out.println(e.getClass().getSimpleName());
}
}
}
#Tasks
👍3
Варианты ответа:
Anonymous Quiz
29%
IOException
12%
IOException
59%
FileNotFoundException
0%
NullPointerException
👍3
Как работает java.util.concurrent.locks.Condition?🤓
Ответ:
Condition — это интерфейс, предоставляющий более гибкий контроль потоков, чем wait()/notify().
Ассоциируется с Lock. Для объекта Lock можно создать одну или несколько Condition (через newCondition()).
Методы:
await() (освобождает lock и ждет),
signal() (пробуждает один поток),
signalAll() (пробуждает все).
Преимущества: можно иметь несколько очередей ожидания для разных условий (например, для производителя и потребителя отдельные Condition).
Также поддерживает прерывания и таймауты.
#собеседование
Ответ:
Ассоциируется с Lock. Для объекта Lock можно создать одну или несколько Condition (через newCondition()).
Методы:
await() (освобождает lock и ждет),
signal() (пробуждает один поток),
signalAll() (пробуждает все).
Преимущества: можно иметь несколько очередей ожидания для разных условий (например, для производителя и потребителя отдельные Condition).
Также поддерживает прерывания и таймауты.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
История технологии сегодня — 4 июня
ℹ️ Кто родился в этот день
Ива́н Влади́мирович Танана́ев (22 мая [4 июня] 1904 года — 28 февраля 1993 года) — советский и российский учёный-химик, специалист в области органической и аналитической химии. Под руководством Тананаева были разработаны способы переработки сырья, найдены новые области применения редкоземельных элементов, проводились исследования хроматов лантана, неодима и иттрия. Впоследствии эти наработки оказались полезными при создании высокотемпературных керамических материалов. Решил важную задачу комплексного освоения минерального сырья на Кольском полуострове. Он разработал технологию выделения из руд ценных металлов и фосфора, которая и в XXI веке применяется на заводах. Также учёный одним из первых сформулировал идеи о наноматериалах.
Кристофер Кокерелл (4 июня 1910 года, Кембридж — 1 июня 1999 года, Хайт, Гэмпшир) — британский инженер, изобретатель судна на воздушной подушке. Патентную заявку на схему судна на воздушной подушке, принципиально новую конструкцию, названную им «hovercraft» («парящий аппарат»), он подал 12 декабря 1955 года. Первый прототип построенного им судна на воздушной подушке SR-N1 (англ. SR.N1) был построен весной 1959 года и всего несколько недель спустя пересёк Ла-Манш за 20 минут.
🌐 Знаковые события
1896 — испытание первого автомобиля, построенного Фордом, было задержано на час, так как оказалось, что автомобиль шире, чем двери цеха, в котором его создавали.
#Biography #Birth_Date #Events #04июня
Ива́н Влади́мирович Танана́ев (22 мая [4 июня] 1904 года — 28 февраля 1993 года) — советский и российский учёный-химик, специалист в области органической и аналитической химии. Под руководством Тананаева были разработаны способы переработки сырья, найдены новые области применения редкоземельных элементов, проводились исследования хроматов лантана, неодима и иттрия. Впоследствии эти наработки оказались полезными при создании высокотемпературных керамических материалов. Решил важную задачу комплексного освоения минерального сырья на Кольском полуострове. Он разработал технологию выделения из руд ценных металлов и фосфора, которая и в XXI веке применяется на заводах. Также учёный одним из первых сформулировал идеи о наноматериалах.
Кристофер Кокерелл (4 июня 1910 года, Кембридж — 1 июня 1999 года, Хайт, Гэмпшир) — британский инженер, изобретатель судна на воздушной подушке. Патентную заявку на схему судна на воздушной подушке, принципиально новую конструкцию, названную им «hovercraft» («парящий аппарат»), он подал 12 декабря 1955 года. Первый прототип построенного им судна на воздушной подушке SR-N1 (англ. SR.N1) был построен весной 1959 года и всего несколько недель спустя пересёк Ла-Манш за 20 минут.
1896 — испытание первого автомобиля, построенного Фордом, было задержано на час, так как оказалось, что автомобиль шире, чем двери цеха, в котором его создавали.
#Biography #Birth_Date #Events #04июня
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🤣1
[Совет по Java #046]
Тема:
Проблема: Перечисления в Java (
Разработчики, пытающиеся добавить общее поведение в разные
Решение: Для добавления общего поведения используйте интерфейсы. Перечисление может реализовывать любое количество интерфейсов.
Вынесите общие методы в интерфейс, а затем реализуйте его в каждом enum. Если нужна общая реализация методов, используйте интерфейс с
Объяснение: Каждое перечисление — это класс, который неявно расширяет
Для сложной логики можно вынести утилитарный класс со статическими методами, работающими с
#Java #советы
Тема:
java.lang.Enum не может наследовать другой класс, потому что уже наследует Enum.Проблема: Перечисления в Java (
enum) неявно наследуются от класса java.lang.Enum. Это значит, что они не могут расширять другой класс — множественное наследование классов в Java запрещено. Разработчики, пытающиеся добавить общее поведение в разные
enum через наследование от базового класса, сталкиваются с ошибкой компиляции. Часто возникает желание создать иерархию перечислений, например, BaseEnum с общими методами и несколько enum-типов от него. Это невозможно из-за финального Enum в корне иерархии.Решение: Для добавления общего поведения используйте интерфейсы. Перечисление может реализовывать любое количество интерфейсов.
Вынесите общие методы в интерфейс, а затем реализуйте его в каждом enum. Если нужна общая реализация методов, используйте интерфейс с
default методами (Java 8+). Также можно добавить поля и конструкторы в enum, но единого предка для разных перечислений не будет. Для передачи общей логики используйте композицию или статические утилитарные методы.public class EnumInterfaces {
// Общий интерфейс для всех перечислений с кодом
interface Codified {
int getCode();
String getDescription();
}
// Базовый интерфейс с default методом
interface Named {
String getName();
default String getFormattedName() {
return "[" + getName() + "]";
}
}
// Перечисление реализует оба интерфейса
enum Status implements Codified, Named {
NEW(1, "Новый"),
PROCESSING(2, "В обработке"),
COMPLETED(3, "Завершен");
private final int code;
private final String description;
Status(int code, String description) {
this.code = code;
this.description = description;
}
@Override
public int getCode() { return code; }
@Override
public String getDescription() { return description; }
@Override
public String getName() { return name(); }
}
enum Priority implements Codified {
LOW(10, "Низкий"),
HIGH(20, "Высокий");
private final int code;
private final String description;
Priority(int code, String description) {
this.code = code;
this.description = description;
}
@Override
public int getCode() { return code; }
@Override
public String getDescription() { return description; }
}
// Полиморфная работа через интерфейс
public static void printCode(Codified c) {
System.out.println(c.getCode() + " -> " + c.getDescription());
}
public static void main(String[] args) {
printCode(Status.NEW);
printCode(Priority.HIGH);
// Использование default метода
System.out.println(Status.COMPLETED.getFormattedName()); // [COMPLETED]
}
}Объяснение: Каждое перечисление — это класс, который неявно расширяет
java.lang.Enum. JVM гарантирует, что у этого класса нет другого суперкласса, что исключает наследование от пользовательских классов. Однако перечисление может реализовывать интерфейсы, что позволяет достичь полиморфизма. Интерфейсы позволяют группировать разные enum под общей абстракцией. Если нужно переиспользовать реализацию методов, используйте default методы интерфейса (Java 8+). Для сложной логики можно вынести утилитарный класс со статическими методами, работающими с
Enum через интерфейсы или рефлексию.#Java #советы
👍5
14. Transactional Outbox: как гарантировать публикацию события
Заказ сохранился в БД, а событие в Kafka — нет. Знакомо?
В этом видео разбираем проблему dual‑write между базой данных и брокером сообщений — когда одно действие выполнено, а другое нет, и система оказывается в несогласованном состоянии.
Почему нельзя просто обернуть всё в @Transactional?
Как гарантировать, что событие будет опубликовано тогда и только тогда, когда данные сохранены?
Ответ — Transactional Outbox.
Что в видео:
Проблема dual‑write — наглядно показываю, как заказ сохраняется, а событие теряется.
Transactional Outbox — что это такое, как работает и почему это стандарт надёжной публикации.
Реализация в Spring Boot:
Таблица outbox_event (Liquibase) JPA сущность и репозиторий
Модификация OrderService – убираю прямую отправку в Kafka
Polling Publisher (@Scheduled) – простой способ доставки событий
Исходный код проекта на GitHub наверняка заслуживает Ваших звезд!🙂
Ссылка на Youtube
Ссылка на Рутьюб
Смотрите, ставьте лайки, подписывайтесь на каналы!✌️
Жду ваших реакций и оценок🙂
Заказ сохранился в БД, а событие в Kafka — нет. Знакомо?
В этом видео разбираем проблему dual‑write между базой данных и брокером сообщений — когда одно действие выполнено, а другое нет, и система оказывается в несогласованном состоянии.
Почему нельзя просто обернуть всё в @Transactional?
Как гарантировать, что событие будет опубликовано тогда и только тогда, когда данные сохранены?
Ответ — Transactional Outbox.
Что в видео:
Проблема dual‑write — наглядно показываю, как заказ сохраняется, а событие теряется.
Transactional Outbox — что это такое, как работает и почему это стандарт надёжной публикации.
Реализация в Spring Boot:
Таблица outbox_event (Liquibase) JPA сущность и репозиторий
Модификация OrderService – убираю прямую отправку в Kafka
Polling Publisher (@Scheduled) – простой способ доставки событий
Исходный код проекта на GitHub наверняка заслуживает Ваших звезд!
Ссылка на Youtube
Ссылка на Рутьюб
Смотрите, ставьте лайки, подписывайтесь на каналы!
Жду ваших реакций и оценок
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Что выведет код?
#Tasks
public enum Task040626 {
FIRST, SECOND;
static String msg = getMsg();
static String getMsg() {
return "hello";
}
Task040626() {
System.out.print(getLength());
}
static int getLength() {
return msg.length();
}
public static void main(String[] args) {
System.out.print("main");
}
}#Tasks
👍2
👍3
Что такое ReadWriteLock? Когда применять?🤓
Ответ:
ReadWriteLock (интерфейс, реализация ReentrantReadWriteLock) разделяет блокировки на чтение и запись.
Правила: несколько потоков могут одновременно захватить блокировку чтения, если нет блокировки записи.
Блокировка записи эксклюзивна — захватывается только одним потоком, и при этом не должно быть активных читателей. Это повышает производительность в системах с частыми чтениями и редкими записями (например, кэш, конфигурация).
Поток, захвативший блокировку чтения, не может "апгрейдиться" до блокировки записи (приведет к deadlock).
#собеседование
Ответ:
Правила: несколько потоков могут одновременно захватить блокировку чтения, если нет блокировки записи.
Блокировка записи эксклюзивна — захватывается только одним потоком, и при этом не должно быть активных читателей. Это повышает производительность в системах с частыми чтениями и редкими записями (например, кэш, конфигурация).
Поток, захвативший блокировку чтения, не может "апгрейдиться" до блокировки записи (приведет к deadlock).
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
История технологии сегодня — 5 июня
ℹ️ Кто родился в этот день
Де́неш Га́бор (Деннис Габор) (венг. Gábor Dénes; 5 июня 1900, Будапешт — 9 февраля 1979, Лондон) — венгерский физик, лауреат Нобелевской премии по физике в 1971 году «за изобретение и развитие голографического метода».
Джон Кауч А́дамс (англ. John Couch Adams; устаревшие написания: Джон Кух Адамс, Джон Кук Адамс, 5 июня 1819, Корнуолл, Англия — 21 января 1892, Кембридж, Англия) — британский математик и астроном, иностранный член-корреспондент Петербургской академии наук, член Лондонского королевского общества. Его наиболее известным достижением было предсказание существования и положения в пространстве Нептуна при помощи одной лишь математики (планета, открытая «на кончике пера»). Расчёты были проведены для объяснения отклонений в орбите Урана от законов Кеплера и Ньютона.
Рудольф Эрнст Па́йерлс (англ. Rudolf Ernst Peierls; 5 июня 1907, Берлин — 19 сентября 1995, Оксфорд) — английский физик-теоретик немецкого происхождения. В 1939 году вместе с Нильсом Бором и Георгом Плачеком исследовал механизм ядерных реакций, индуцированных нейтронами, на основе сформулированной ими оптической теоремы и представлений о составном ядре. В 1940 году совместно с Отто Фришем оценил критическую массу урана-235, которая оказалась не столь велика, как считалось ранее. Этот результат был изложен в так называемом «меморандуме Фриша — Пайерлса», который во многом инициировал широкомасштабные исследования возможности создания ядерного вооружения. Пайерлс также участвовал в вычислениях характеристик цепных реакций и разработке методов разделения изотопов.
🌐 Знаковые события
1783 — французские изобретатели братья Монгольфье в родном городке Анноне запустили на высоту 500 м первый в мире тепловой аэростат (воздушный шар).
1977 — в продаже появился первый персональный компьютер Apple II.
1998 — запущен Open Directory Project.
2025 — выход игровой системы Nintendo Switch 2.
#Biography #Birth_Date #Events #05июня
Де́неш Га́бор (Деннис Габор) (венг. Gábor Dénes; 5 июня 1900, Будапешт — 9 февраля 1979, Лондон) — венгерский физик, лауреат Нобелевской премии по физике в 1971 году «за изобретение и развитие голографического метода».
Джон Кауч А́дамс (англ. John Couch Adams; устаревшие написания: Джон Кух Адамс, Джон Кук Адамс, 5 июня 1819, Корнуолл, Англия — 21 января 1892, Кембридж, Англия) — британский математик и астроном, иностранный член-корреспондент Петербургской академии наук, член Лондонского королевского общества. Его наиболее известным достижением было предсказание существования и положения в пространстве Нептуна при помощи одной лишь математики (планета, открытая «на кончике пера»). Расчёты были проведены для объяснения отклонений в орбите Урана от законов Кеплера и Ньютона.
Рудольф Эрнст Па́йерлс (англ. Rudolf Ernst Peierls; 5 июня 1907, Берлин — 19 сентября 1995, Оксфорд) — английский физик-теоретик немецкого происхождения. В 1939 году вместе с Нильсом Бором и Георгом Плачеком исследовал механизм ядерных реакций, индуцированных нейтронами, на основе сформулированной ими оптической теоремы и представлений о составном ядре. В 1940 году совместно с Отто Фришем оценил критическую массу урана-235, которая оказалась не столь велика, как считалось ранее. Этот результат был изложен в так называемом «меморандуме Фриша — Пайерлса», который во многом инициировал широкомасштабные исследования возможности создания ядерного вооружения. Пайерлс также участвовал в вычислениях характеристик цепных реакций и разработке методов разделения изотопов.
1783 — французские изобретатели братья Монгольфье в родном городке Анноне запустили на высоту 500 м первый в мире тепловой аэростат (воздушный шар).
1977 — в продаже появился первый персональный компьютер Apple II.
1998 — запущен Open Directory Project.
2025 — выход игровой системы Nintendo Switch 2.
#Biography #Birth_Date #Events #05июня
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Раздел 11. Работа с файлами, I/O и сетью (NIO.2)
Глава 1. Классический Java I/O (java.io)
FileOutputStream – запись байтов в файл. Путь данных от heap к диску
Как и
Конструкторы и режимы открытия файла
Режим перезаписи (append = false)
При открытии в режиме перезаписи конструктор выполняет следующую последовательность:
Валидация пути. Проверка на null, проверка родительской директории на существование и возможность создания файла.
Создание или усечение файла. Системный вызов
Установка позиции записи. Указатель файла устанавливается в начало — позицию 0.
Создание объекта. Выделение
Этот режим опасен при случайном использовании: открытие существующего файла на запись без
Режим добавления (append = true)
Режим добавления открывает файл с флагами
Это критично для сценариев, где несколько процессов или потоков пишут в один файл параллельно: каждая запись добавляется в конец без риска перезаписи данных другого писателя.
Однако
#Java #для_новичков #beginner #IO #NIO #FileOutputStream
Глава 1. Классический Java I/O (java.io)
FileOutputStream – запись байтов в файл. Путь данных от heap к диску
FileOutputStream — конкретная реализация OutputStream, предназначенная для записи байтов в файл файловой системы. Он представляет собой низкоуровневый мост между Java-кодом и операционной системой: каждый вызов write() транслируется в системный вызов write() ядра ОС, который взаимодействует с файловой системой, страничным кэшем и, в конечном итоге, с блочным устройством хранения.Как и
FileInputStream, FileOutputStream не выполняет внутреннюю буферизацию. Каждый вызов write(int) напрямую обращается к ОС, что делает посимвольную запись крайне неэффективной. Однако именно эта прямота делает FileOutputStream полезным как underlying поток для буферизующих оберток (BufferedOutputStream) или как инструмент для сценариев, где требуется точный контроль над моментом физической записи.Конструкторы и режимы открытия файла
FileOutputStream предоставляет несколько конструкторов, различающихся способом указания файла и режимом открытия:// Перезапись: если файл существует, содержимое уничтожается
public FileOutputStream(String name) throws FileNotFoundException
// Режим добавления: запись начинается с конца существующего файла
public FileOutputStream(String name, boolean append) throws FileNotFoundException
// Аналогичные конструкторы с File вместо String
public FileOutputStream(File file) throws FileNotFoundException
public FileOutputStream(File file, boolean append) throws FileNotFoundException
Режим перезаписи (append = false)
При открытии в режиме перезаписи конструктор выполняет следующую последовательность:
Валидация пути. Проверка на null, проверка родительской директории на существование и возможность создания файла.
Создание или усечение файла. Системный вызов
open() с флагами O_WRONLY | O_CREAT | O_TRUNC. Если файл существует, его содержимое уничтожается, размер сбрасывается в ноль. Если файл не существует, создается новый пустой файл.Установка позиции записи. Указатель файла устанавливается в начало — позицию 0.
Создание объекта. Выделение
FileOutputStream в heap JVM, инициализация полей, включая FileDescriptor с файловым дескриптором ОС.Этот режим опасен при случайном использовании: открытие существующего файла на запись без
append = true безвозвратно удаляет его содержимое. В production-коде рекомендуется явно указывать режим, даже если требуется перезапись, для самодокументирования намерений.Режим добавления (append = true)
Режим добавления открывает файл с флагами
O_WRONLY | O_CREAT | O_APPEND. Ключевое отличие: флаг O_APPEND гарантирует атомарное позиционирование указателя в конец файла перед каждой операцией записи. Это критично для сценариев, где несколько процессов или потоков пишут в один файл параллельно: каждая запись добавляется в конец без риска перезаписи данных другого писателя.
// Безопасное добавление в лог-файл из нескольких потоков
public void appendToLog(String message) throws IOException {
byte[] data = message.getBytes(StandardCharsets.UTF_8);
try (FileOutputStream fos = new FileOutputStream("app.log", true)) {
fos.write(data);
fos.write('\n');
}
}
Однако
FileOutputStream с append = true не обеспечивает потокобезопасность на уровне Java: два потока, одновременно вызывающие write(), могут перемешать байты внутри одного вызова, так как write(byte[]) не атомарен. Для потокобезопасной записи требуется внешняя синхронизация или использование java.nio.channels.FileChannel с блокировками.#Java #для_новичков #beginner #IO #NIO #FileOutputStream
👍4