Java for Beginner
870 subscribers
1.01K photos
275 videos
14 files
1.69K links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Что выведет код?

import java.util.concurrent.locks.*;
import java.util.concurrent.TimeUnit;

public class Task100726 {
private static final Lock lock = new ReentrantLock();
private static final Condition condition = lock.newCondition();
private static volatile boolean flag = false;

public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
lock.lock();
try {
if (!flag) {
condition.await(3, TimeUnit.SECONDS);
}
System.out.print("Done");
} catch (InterruptedException e) {
System.out.print("Interrupted");
} finally {
lock.unlock();
}
});
t.start();
t.join();
}
}


#Tasks
👍3
Что такое CompletableFuture (цепочки и комбинаторы)? 🤓

Ответ:

CompletableFuture (Java 8) реализует Future и CompletionStage.

Позволяет строить цепочки асинхронных операций: thenApply (преобразование), thenAccept (потребление), thenRun (действие без результата).

Для комбинирования: thenCombine (объединение двух результатов), thenCompose (плоское сцепление), anyOf (первый завершившийся), allOf (все завершились).

Можно обрабатывать исключения через exceptionally и handle. Позволяет создавать неблокирующие, реактивные системы без внешних библиотек.



#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
История технологии сегодня — 11 июля

ℹ️ Кто родился в этот день

Алекса́ндр Миха́йлович Про́хоров (11 июля 1916, Атертон, штат Квинсленд, Австралия — 8 января 2002, Москва) — советский и российский физик, один из основоположников важнейшего направления современной физики — квантовой электроники, лауреат Нобелевской премии по физике за 1964 год, один из изобретателей лазерных технологий.

Серге́й Никола́евич Верно́в (28 июня [11 июля] 1910, Сестрорецк, Санкт-Петербургская губерния — 26 сентября 1982, Москва) — российский и советский физик, академик АН СССР (1968), специалист в области физики космических лучей. Один из участников открытия внешнего радиационного пояса Земли.


🌐 Знаковые события

2006 — компания Microsoft прекратила техническую поддержку операционных систем Windows 98 и Windows Me.

2022 — опубликовано первое изображение, полученное космическим телескопом «Джеймс Уэбб». Это изображение ранней Вселенной с самым высоким разрешением из когда-либо сделанных ранее.


#Biography #Birth_Date #Events #11июля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Немного о ИИ.

Всем привет.

Сегодня завтракая, я прочитал довольно интересную статью на Хабре (ссылка).

Она явно перекликается с тем, что последнее время, мне много с кем пришлось обсуждать вопрос - а что нас ждет в мире с ИИ?

Давайте я коротко определю стороны вопроса:

1. Оптимисты

Те кто уверен что использование ИИ - благо. В программировании, в управлении предприятием и государством, в приготовлении на кухне и даже в постели с женой. Используют условный Claude каждый день и крайне довольны результатами.
Доводы: явный быстрый доступ к любым знаниям, значительное увеличение скорости процессов, снижение затрат на данные процессы.


2. Воздержавшиеся (похуисты)

Тем кому ИИ побоку. Шахтеры, строители, землекопы и ногтеточицы. Уверены что их работу ИИ не заменит, а те кто якобы "пострадал" от ИИ - унылые лентяи.
Доводы: нас не заменят, до нас пока дойдет, не выёбывайся - бери сварочный и пошли на завод.


3. Реалисты

Те кто погружен в тему работы ИИ понимая ограничения и последствия. Используют ИИ так же каждый день в сложных темах.
Доводы: ИИ не панацея и не может заменить реальное обучение и человеческий мозг. Не имеет интуиции и понимая последствий своих решений. Употреблять строго по инструкции и с здоровой долей скептицизма.


Кроме вышеозначенных сторон конечно же есть те кто вынужден топить за популяризацию ИИ, так как с этого лутает денюжку. Они же продадут вам кусок говна лишь бы была прибыль. Думаю их распознать довольно не сложно.

В остальном среднестатистический человек просто в ожидании - чем вся эта вакханалия закончится.


Мое мнение

Я уверенно могу сказать что с скептицизмом отношусь к будущему с ИИ. Статья которую я предложил вначале - плюс-минус соответствует моему мнению и прогнозам.

Так же в одной из статей прочитанных ранее мне откликнулось мнение (перефразирую) - умного и погруженного в вопрос человека кооперация с ИИ только усилит, потому что он и без него знает вопрос, а поверхностного данный паразитизм заставит поверить в глубину своих знаний и спотыкаться при каждом удобном случае.

Недавно на собеседовании меня спросили как я отношусь к ИИ в работе. Я ответил, что не доверяю агентам которые неявно могут что-то сломать в сложных системах. Наверно из-за этого меня не взяли))) Но мнения я своего не поменял.

Я вижу насколько удобна ИИ каждый день. Это и советчик и мотиватор. Это доступ к любым знаниям в удобоваримом для меня формате. ЛЛМ может и код написать и песню спеть. Короче просто незаменимая весчь, блин.


Но моё чутье чует ловушки:

1. Незаменимый компаньон

Очень надеюсь вам не приходилось складывать яйца в один пакет, а потом его ронять. Неприятно. Или давать доступ к серверу лучшему другу, а потом обнаружить, что он продан. Крайне неприятно.

ЛЛМ сейчас становится тем инструментом без которого становится крайне сложно обойтись. Кому-то вообще невозможно.

А что если его завтра не станет? Ломка? Нарушение ежедневных отлаженных процессов? И пойдет условный дядя снимать шапки в подворотнях чтобы оплатить токены, ведь цены будут расти (грубая аналогия родом из 90-х, но думаю от этого не менее понятная).

Уже сейчас решают как ограничить доступ к популярным бесплатным ЛЛМ.

Дальше будет хуже. Нас подсадили, а потом будут снимать сливки.


2. Отупение и деградация

Очень противоречивый но явный тезис. Человек стремиться идти по простому пути - закон сохранения энергии в действии.

Чтобы получить знание надо придумать и провести эксперимент. Или послушать выводы того кто его осознал и провел. Или прочитать книгу того кто слушал выводы проводившего эксперимент и обогатил его своими умозаключениями. Или пойти в институт где умные люди прочитавшие много подобных книг и обогатившие эти знания индивидуальным опытом, расскажут выводы эксперимента. И так далее.
Но во всем этом пути так или иначе задействован человеческий мозг и сознание. С необходимой долей скептицизма и осторожности к каждому выводу.

ЛЛМ устраняет все эти нюансы. Выводы (в том числе и не правильные) попавшие в выборку ее обучения не анализируется, а лишь токенизируется по словам. Запрос по данному вопросу порождает не глубокий анализ и скептицизм а лишь правильный в зависимости от промпта набор слов.

И люди верят. В глубокий анализ и понимание. И начинают внемлить и прославлять.

ЛЛМ имеет у нас колоссальный кредит доверия, вы заметили?

Зачем мне решать сложный пример в голове когда ллм (калькулятор) сделает это быстрее? Тут вы можете сказать что калькуляторы существуют уже поколение а вроде тупее никто не стал?
А я отвечу - стал.

Я один из тех кто умеет считать на логарифмической линейке. Многие из тех кто это прочитает даже не знают что это такое. А раньше с ней дома строили.

С каждым улучшением производительности наши знания уходят на более высокий уровень абстракции. ИИ - это еще более высокая ступень.
Скоро мы сможем создать космический корабль, но не будем знать как он работает. И это пугает.

Школьник решает сложный пример, но не запоминает выводов приведших к решению. А зачем ведь ллм всегда рядом.

Будущее будет сложным.


3. Политика

Уже сейчас даже не искушенный понимает что ИИ становится проводником политических ценностей той страны где он запущен. Еще неявно, но неотвратимо. ЛЛМ превращается в стратегическое оружие, обладание которым будет не менее важным чем обладание ЯО.

Мы с вами фактически отрезаны от западных моделей, их и наше государство делает все чтобы доступов было все меньше. Восток хоть и дружественен но тоже думаю скоро будет обрезать или ограничивать каналы.
Свои ЛЛМ есть но они пока на уровне 2-4 летней давности западных. Что будет в ближайшие годы - покажет как страна будет жить в будущем.


Выводы.

А их не будет.

Делайте их сами для себя в зависимости от вашей степени привыкания и окружения.

То что псевдоИИ уже тут - это факт. Возможно в ближайшие 5 лет и полноценный ИИ появится.

Что будет с человеком остается только догадываться.

Как по мне - оставайтесь людьми с своей головой на плечах.

=====================================

А что думаете Вы? Готов подискутировать.

Сможете ли вы сегодня обойтись без ллм?
👍7🔥1
История технологии сегодня — 12 июля

ℹ️ Кто родился в этот день

Уиллис Юджин Лэмб (англ. Willis Eugene Lamb; 12 июля 1913, Лос-Анджелес, США — 15 мая 2008, Тусон, США) — американский физик, лауреат Нобелевской премии по физике в 1955 г. (половина премии «за открытия, связанные с тонкой структурой спектра водорода»).


🌐 Знаковые события

2011 — Нептун завершил свой первый с момента открытия планеты в 1846 году полный оборот вокруг Солнца.


#Biography #Birth_Date #Events #12июля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🤓2
🆒2
Скоро... 🧑‍💻

Ждете?
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
16. Saga Orchestration: централизованное управление с Camunda

В этом видео мы переходим к Saga Orchestration — централизованному управлению распределёнными транзакциями. Вместо того чтобы встраивать Camunda в существующие сервисы, мы создаём выделенный workflow-service, который становится единственным владельцем бизнес-процесса. Kafka остаётся транспортом, Camunda становится мозгом.

BPM Service:
- принимает решения, а не просто пересылает сообщения;
- управляет порядком шагов и компенсациями;
- обрабатывает таймауты на уровне BPMN;
- предоставляет полную видимость процесса через Camunda Cockpit.

Ключевые темы видео:

Command vs Event — принципиальное различие
Жизненный цикл процесса в Camunda (Process Definition → Instance → Waiting → Completed)
Message Correlation — как Camunda находит нужный процесс среди тысяч других
BPMN-диаграмма с Event-Based Gateway (ветки успеха и ошибки)
JavaDelegate для публикации команд в Kafka Компенсирующие транзакции и таймауты без единой строчки кода Camunda
Cockpit — мониторинг бизнес-процессов

Исходный код проекта на GitHub наверняка заслуживает Ваших звезд! 🙂

Ссылка на Youtube
Ссылка на Рутьюб

Смотрите, ставьте лайки, подписывайтесь на каналы!✌️

Жду ваших реакций и оценок
🙂
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
История технологии сегодня — 13 июля

ℹ️ Кто родился в этот день

Ариста́рх Аполло́нович Белопо́льский (1 июля [13 июля] 1854, Москва — 16 мая 1934, Пулково) — русский и советский астроном и астрофизик. Разработал метод и сконструировал прибор, с помощью которого первым получил экспериментальное доказательство существования эффекта Доплера применительно к световым волнам; применил эффект Доплера, проявляющийся в виде смещения спектральных линий в оптических спектрах, для исследований в астроспектроскопии; в числе первых определил элементы орбит нескольких переменных и спектрально-двойных звёзд, исследовал спектры новых звёзд и солнечной поверхности, краев и короны; — лучевые скорости небесных светил, один из пионеров в фотографировании их спектров с помощью спектрографов; обнаружил периодическое изменение лучевой скорости у цефеид; всесторонние исследования комет, — вращения около оси ВенерыЮпитера и колец Сатурна.


🌐 Знаковые события

1897 — Гульельмо Маркони получил патент на радио в США.


#Biography #Birth_Date #Events #13июля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Раздел 11. Работа с файлами, I/O и сетью (NIO.2)

Глава 2. Современный NIO.2 (java.nio.file)

Создание файлов и директорий

Класс Files предоставляет набор статических методов для создания файловых объектов на диске. Эти методы отличаются от конструкторов старого java.io.File тем, что работают непосредственно с файловой системой и выбрасывают конкретные исключения при ошибках. В отличие от File.createNewFile(), который возвращал boolean без объяснения причин отказа, методы NIO.2 сообщают точно, что пошло не так: файл уже существует, нет прав на запись, родительская директория отсутствует и т.д.

Файловая система — это способ организации, хранения, именования, доступа и управления файлами на устройстве хранения данных. Она определяет структуру директорий, права доступа, метаданные файлов и механизмы их поиска.


Создание пустого файла: Files.createFile(Path)


Метод Files.createFile(Path path, FileAttribute<?>... attrs) создаёт новый пустой файл по указанному пути. Если файл уже существует — выбрасывает FileAlreadyExistsException. Если родительская директория не существует — выбрасывает NoSuchFileException.
import java.nio.file.*;
import java.io.IOException;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.Set;

public class FileCreator {

public void createEmptyFile(Path path) throws IOException {
// Проверяем, существует ли родительская директория
Path parent = path.getParent();
if (parent != null && Files.notExists(parent)) {
throw new NoSuchFileException(
"Родительская директория не существует: " + parent
);
}

// Создаём файл с правами доступа (только Unix)
Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rw-r--r--");
FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perms);

Files.createFile(path, attr);
}
}

Параметр FileAttribute<?>... attrs — это varargs массив атрибутов файла, которые устанавливаются атомарно при создании. На POSIX-системах через него передаются права доступа. На Windows этот параметр игнорируется, так как модель прав Windows основана на ACL (Access Control List, список контроля доступа), а не на POSIX-битах.

Атомарность создания означает, что файл либо создаётся полностью с указанными атрибутами, либо не создаётся вообще. Другие процессы не увидят файл без атрибутов. Это критично для безопасности: например, если вы создаёте файл с секретными данными и хотите, чтобы он сразу имел ограниченные права rw------- (только владелец).

Важное отличие от File.createNewFile(): Files.createFile() гарантирует, что файл создан именно вашим вызовом. Если между проверкой exists() и вызовом createFile() другой процесс создал файл, createFile() выбросит исключение, а не молча вернёт false. Это устраняет race condition (состояние гонки) — ситуацию, когда результат операции зависит от порядка выполнения конкурирующих потоков или процессов.


Создание одной директории: Files.createDirectory(Path)

Метод Files.createDirectory(Path dir, FileAttribute<?>... attrs) создаёт одну директорию. Все промежуточные директории в пути уже должны существовать. Если директория существует — FileAlreadyExistsException. Если родитель отсутствует — NoSuchFileException.
public void createSingleDirectory(Path dir) throws IOException {
// Создаём только конечную директорию
// Предполагаем, что /var/log уже существует
Path appLogs = Paths.get("/var/log/myapp");
Files.createDirectory(appLogs);
}

Этот метод полезен, когда вы хотите явно контролировать каждый уровень иерархии и получать ошибку, если структура не соответствует ожиданиям. Например, в установщике приложения, где отсутствие ожидаемой родительской директории может сигнализировать о неправильной конфигурации системы.


Создание вложенных директорий: Files.createDirectories(Path)

Метод Files.createDirectories(Path dir, FileAttribute<?>... attrs) создаёт директорию и все несуществующие родительские директории в пути. Это аналог команды mkdir -p в Unix. Если конечная директория уже существует — метод молча возвращает управление, не выбрасывая исключение. Если путь существует, но не является директорией — выбрасывает FileAlreadyExistsException.
public void createNestedStructure() throws IOException {
Path deepPath = Paths.get("data", "books", "2024", "reviews");

// Создаёт data/, data/books/, data/books/2024/, data/books/2024/reviews/
Files.createDirectories(deepPath);

// Проверяем, что создано
System.out.println("Создана структура: " + deepPath.toAbsolutePath());
System.out.println("Количество сегментов: " + deepPath.getNameCount());
}

createDirectories() — идемпотентный метод: повторный вызов с тем же путём не приводит к ошибке. Это делает его идеальным для инициализации структуры приложения при старте.

Идемпотентность — это свойство операции, при котором повторное выполнение даёт тот же результат, что и первое. В контексте файловых операций это означает, что createDirectories() можно вызывать сколько угодно раз — структура останется корректной.


#Java #для_новичков #beginner #IO #NIO #Files #copy
👍6
Создание временных файлов и директорий

Files.createTempFile(String prefix, String suffix)
Создаёт временный файл в системной временной директории (java.io.tmpdir). Имя генерируется атомарно и гарантированно уникально в пределах JVM-процесса.
Path tempFile = Files.createTempFile("report_", ".tmp");
// Результат: /tmp/report_1234567890.tmp

Префикс и суффикс позволяют идентифицировать назначение файла. Атомарность генерации имени означает, что даже при конкурентном вызове из нескольких потоков имена не пересекутся.

Files.createTempFile(Path dir, String prefix, String suffix)

Создаёт временный файл в указанной директории, а не в системной временной.
Path customDir = Paths.get("/app/temp");
Files.createDirectories(customDir);
Path tempInCustom = Files.createTempFile(customDir, "session_", ".dat");

Это важно, когда системная временная директория (/tmp на Linux) монтируется в tmpfs (файловая система в памяти) с ограниченным размером, а ваши временные файлы большие. В таком случае лучше использовать директорию на диске.

tmpfs — это виртуальная файловая система, хранящая данные в оперативной памяти (RAM) вместо диска. Она быстрая, но ограничена объёмом ОЗУ. /tmp на многих Linux-дистрибутивах монтируется как tmpfs.

Files.createTempDirectory(String prefix)

Создаёт временную директорию в системной временной директории.
Path tempDir = Files.createTempDirectory("batch_processing_");
// Результат: /tmp/batch_processing_1234567890/


Files.createTempDirectory(Path dir, String prefix)

Создаёт временную директорию в указанной родительской директории.
Path workDir = Paths.get("/var/app/work");
Path tempWorkDir = Files.createTempDirectory(workDir, "job_");



Копирование файлов: Files.copy()

Базовое копирование: Files.copy(Path source, Path target, CopyOption... options)
Метод копирует файл или директорию по указанному пути. Для директории копируется только сама директория как пустая сущность, без содержимого. Для рекурсивного копирования дерева требуется ручной обход.
Path src = Paths.get("/data/report.txt");
Path dst = Paths.get("/backup/report.txt");

Files.copy(src, dst); // FileAlreadyExistsException, если dst существует


StandardCopyOption.REPLACE_EXISTING
Разрешает перезапись существующего файла назначения. Без этой опции Files.copy() выбросит FileAlreadyExistsException.
Files.copy(src, dst, StandardCopyOption.REPLACE_EXISTING);


StandardCopyOption.COPY_ATTRIBUTES

Копирует метаданные файла: временные метки (creation time, last modified time, last access time) и POSIX-права (на Unix). Без этой опции новый файл получает текущее время и права по умолчанию (umask).
umask (user file-creation mode mask) — это маска прав доступа в Unix, которая определяет, какие биты прав сбрасываются при создании нового файла. Например, umask 022 означает, что у новых файлов не будут прав на запись для группы и остальных.
Files.copy(src, dst, 
StandardCopyOption.REPLACE_EXISTING,
StandardCopyOption.COPY_ATTRIBUTES
);


StandardCopyOption.ATOMIC_MOVE

Не применяется к copy(), только к move(). При передаче в copy() выбросит UnsupportedOperationException.

Копирование из потока: Files.copy(InputStream in, Path target, CopyOption... options)
Читает все байты из InputStream и записывает их в файл. Поток закрывается автоматически. Удобно для загрузки данных из сети или других источников.
import java.net.URL;

public void downloadFile(String urlString, Path target) throws IOException {
URL url = new URL(urlString);
try (InputStream in = url.openStream()) {
// Копируем всё содержимое потока в файл
// CREATE — создать файл, если нет
// REPLACE_EXISTING — перезаписать, если есть
long bytesCopied = Files.copy(in, target,
StandardCopyOption.REPLACE_EXISTING
);
System.out.println("Скопировано байт: " + bytesCopied);
}
// InputStream закрыт автоматически try-with-resources
}



Метод возвращает количество скопированных байт как long. Это полезно для логирования и проверки целостности.

Копирование в поток: Files.copy(Path source, OutputStream out)
Читает все байты из файла и записывает их в OutputStream. Поток не закрывается автоматически — управление потоком остаётся на вызывающей стороне.
public void streamFileToResponse(Path file, OutputStream responseOut) throws IOException {
// Отправляем файл в HTTP-ответ
// responseOut управляется внешним кодом (сервлет, фреймворк)
long bytesSent = Files.copy(file, responseOut);
responseOut.flush(); // явно сбрасываем буфер
}

Этот метод эффективен, так как внутри использует нативный механизм zero-copy (нулевое копирование) через transferTo() файлового канала, если поток поддерживает запись в канал. Zero-copy означает, что данные передаются от диска к сетевому сокету без промежуточного копирования в пользовательское пространство JVM, что снижает нагрузку на CPU и память.


Копирование директорий: Files.copy() не рекурсивно
Критически важно понимать: Files.copy() для директории копирует только саму директорию как пустую сущность. Все файлы и поддиректории внутри не копируются. Для полного копирования дерева требуется ручной обход.
import java.nio.file.*;
import java.io.IOException;
import java.util.stream.Stream;

public class DirectoryCopier {

public void copyDirectory(Path source, Path target) throws IOException {
// Проверяем, что источник — директория
if (!Files.isDirectory(source)) {
throw new NotDirectoryException(source.toString());
}

// Создаём корневую директорию назначения
// createDirectories идемпотентен — не бросает исключение, если уже есть
Files.createDirectories(target);

// Обходим дерево источника
try (Stream<Path> walk = Files.walk(source)) {
walk.forEach(srcPath -> {
try {
// Вычисляем относительный путь от корня источника
Path relative = source.relativize(srcPath);
// Резолвим его относительно корня назначения
Path dstPath = target.resolve(relative);

if (Files.isDirectory(srcPath)) {
// Создаём директорию
Files.createDirectories(dstPath);
} else {
// Копируем файл
Files.copy(srcPath, dstPath,
StandardCopyOption.REPLACE_EXISTING,
StandardCopyOption.COPY_ATTRIBUTES
);
}
} catch (IOException e) {
// Оборачиваем в unchecked для использования внутри forEach
throw new UncheckedIOException(e);
}
});
}
}
}

В этом коде Files.walk(source) возвращает поток всех путей в дереве источника, включая корень. source.relativize(srcPath) вычисляет относительный путь от корня, а target.resolve(relative) строит соответствующий путь в дереве назначения. Порядок обхода гарантирован — walk() обходит в порядке pre-order (сначала родитель, потом дети), поэтому директории создаются до файлов внутри них.

Pre-order обход — это стратегия обхода дерева, при которой узел обрабатывается до его потомков. В контексте файловой системы это означает, что директория создаётся перед файлами внутри неё.

#Java #для_новичков #beginner #IO #NIO #Files #copy
👍6
Путь байтов в памяти JVM при создании и копировании

Создание файла: путь данных
Когда вы вызываете Files.createFile(path):
Объект Path уже находится в куче (Heap). Строковые сегменты пути — это String-объекты, хранящие массивы символов (char[]) в куче.
Метод createFile() вызывает FileSystemProvider.createFile(). Провайдер извлекает байтовое представление пути: на Unix это массив байтов в кодировке UTF-8, на Windows — UTF-16LE (wchar_t[]).
Байты пути копируются из кучи JVM в нативную память через JNI. Системный вызов open() с флагом O_CREAT | O_EXCL (POSIX) атомарно создаёт файл, если он не существует. Флаг O_EXCL гарантирует, что если файл уже есть, вызов вернёт ошибку EEXIST — JVM преобразует её в FileAlreadyExistsException.
Вновь созданный файл представлен в ядре ОС структурой inode (Unix) или записью в MFT (NTFS). Права доступа устанавливаются через fchmod() или аналогичный вызов, если были переданы FileAttribute.
Возвращаемое значение createFile() — это объект Path, переданный в метод (тот же самый объект, без копирования). Никаких новых объектов в куче не создаётся, за исключением возможного внутреннего объекта исключения, если операция не удалась.


Копирование файла: путь данных

При Files.copy(source, target):
Источник и назначение — объекты Path в куче. Метод определяет FileStore (хранилище) для обоих путей через FileSystemProvider.getFileStore().
Если источник и назначение на одном FileStore (один раздел диска), некоторые провайдеры могут использовать оптимизацию reflink (copy-on-write копирование) — вместо физического копирования блоков данных создаётся новая ссылка на те же блоки. Изменение любой из копий приведёт к физическому копированию изменённых блоков. Это поддерживается файловыми системами Btrfs и XFS на Linux.
Если оптимизация недоступна, выполняется классическое копирование: данные читаются из источника через кэш страниц ОС в нативную память, затем записываются в назначение. При этом данные проходят через пространство пользователя (user space) JVM — два системных вызова на каждый блок: read() и write().

Для больших файлов внутренняя реализация Files.copy() использует буфер фиксированного размера (обычно 8 КБ или 32 КБ). Этот буфер — массив byte[] в куче, который создаётся один раз и переиспользуется. При копировании файла размером 1 ГБ буфер создаётся один раз, а не для каждого блока, что минимизирует давление на GC.
Если передан COPY_ATTRIBUTES, после копирования данных выполняется дополнительный системный вызов для установки метаданных: utimensat() для временных меток, fchmod() для прав.
Все временные объекты — буфер копирования, массивы байтов пути — создаются в Young Generation. Если операция быстрая (маленький файл), они уничтожаются при следующей Minor GC. Если файл большой и операция длительная, буфер может пережить несколько циклов Minor GC и быть перемещён в Survivor Space, а затем в Old Generation при достижении порога возраста.

Survivor Space — это одно из двух пространств (S0 или S1) в Young Generation, куда перемещаются объекты, пережившие Minor GC. Объекты "прыгают" между S0 и S1, и при достижении определённого количества циклов сборки (tenuring threshold) перемещаются в Old Generation.


Создание директорий: путь данных

Files.createDirectories() выполняет итерацию по сегментам пути. Для каждого сегмента:
Строится промежуточный Path (в куче) — это лёгкий объект, создаваемый быстро.
Выполняется системный вызов mkdir(). Если директория уже существует — ошибка EEXIST, которую метод игнорирует (идемпотентность).
Если переданы FileAttribute, применяются chmod().
Промежуточные объекты Path становятся мусором сразу после итерации. При создании глубокой иерархии (data/books/2024/reviews) создаётся 4 временных объекта Path — все они собираются при первой Minor GC.

#Java #для_новичков #beginner #IO #NIO #Files #copy
👍6
Что выведет код?

import java.io.*;
import java.nio.file.*;

public class Task130726 {
public static void main(String[] args) {
boolean created1 = false;
try {
File file = new File("parent/child.txt");
created1 = file.createNewFile();
} catch (IOException e) {
created1 = false;
}
System.out.print(created1 + " ");

boolean created2 = false;
try {
Path path = Paths.get("parent/child2.txt");
Files.createFile(path);
created2 = true;
} catch (IOException e) {
created2 = false;
}
System.out.print(created2);
}
}


#Tasks
👍2
Варианты ответа:
Anonymous Quiz
62%
true true
0%
true false
23%
false true
15%
false false
👍3
Что такое WatchService в NIO? 🤓

Ответ:

java.nio.file.WatchService (Java 7)
— сервис для отслеживания изменений в файловой системе (создание, удаление, изменение файлов/директорий).

Регистрируется с помощью Path.register(WatchService, WatchEvent.Kind...). Получает события через take() или poll().

Полезен для мониторинга конфигураций, загрузчиков файлов, автоматической перекомпиляции. Поддерживается на большинстве ОС.

Реализует эффективный механизм уведомлений на уровне ядра (не требует опроса).



#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
История технологии сегодня — 14 июля

ℹ️ Кто родился в этот день

Джей Райт Фо́ррестер (англ. Jay Wright Forrester; 14 июля 1918, Анселмо, Небраска — 16 ноября 2016, Конкорд, Массачусетс) — американский инженер и системолог, разработчик теории системной динамики. Был разработчиком одного из первых универсальных компьютеров Whirlwind I («Вихрь-1») по заказу ВМС США, в основанной им лаборатории цифровых компьютеров при МТИ. В рамках этих исследований им в 1950 году была предложена одна из схем рабочей памяти на ферритовых сердечниках, получившей широкое распространение на ЭВМ второго поколения.


🌐 Знаковые события

1954 — Принстонский университет в США впервые объявил о сдаче компьютеров в частное пользование.

1983 — вышла компьютерная игра Mario Bros.


#Biography #Birth_Date #Events #14июля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
[Совет по Java #060]

Тема: CountDownLatch нельзя переиспользовать после достижения нуля.

Проблема: CountDownLatch — это синхронизатор, позволяющий одному или нескольким потокам ожидать, пока набор операций в других потоках не завершится. Счетчик уменьшается вызовами countDown() и, достигнув нуля, освобождает все ожидающие потоки. Однако после этого счетчик не может быть сброшен — он остается на нуле, и любые последующие вызовы await() будут немедленно возвращать управление, не блокируя потоки.

Это делает CountDownLatch одноразовым инструментом. Разработчики, не знакомые с этим ограничением, могут попытаться повторно использовать экземпляр для нескольких фаз синхронизации, что приведет к неверной логике или состояниям гонки. В сценариях, где требуется многократная синхронизация групп потоков (например, в циклах итераций или периодических вычислениях), попытка повторно использовать один и тот же CountDownLatch приводит к тому, что вторая фаза начинается немедленно, без ожидания всех потоков, что нарушает корректность.

Решение: Для многоразовой синхронизации используйте CyclicBarrier, который позволяет группе потоков ожидать друг друга на барьере, и после достижения барьера автоматически сбрасывается для следующего использования. CyclicBarrier может принимать опциональное действие, выполняемое при достижении барьера (например, агрегация данных).

Если требуется накопление событий с возможностью сброса, можно использовать Semaphore с подсчетом разрешений, но это менее удобно. Для сложных сценариев с несколькими фазами применяйте Phaser, который предоставляет более гибкую и масштабируемую синхронизацию с динамической регистрацией сторон.
public class LatchVsBarrier {

public static void main(String[] args) throws InterruptedException {
//CountDownLatch одноразовый
CountDownLatch latch = new CountDownLatch(3);

// Первая фаза: ожидаем 3 потока
for (int i = 0; i < 3; i++) {
new Thread(() -> {
// работа
latch.countDown();
}).start();
}
latch.await(); // ждем завершения первой фазы
System.out.println("Первая фаза завершена");

// Попытка второй фазы — бессмысленна, latch уже на нуле
// Новые потоки, вызывающие latch.await(), пройдут без ожидания
// latch.countDown() не имеет эффекта

//CyclicBarrier переиспользуется
CyclicBarrier barrier = new CyclicBarrier(3, () ->
System.out.println("Барьер достигнут, выполняется действие"));

Runnable task = () -> {
try {
// Первая итерация
System.out.println(Thread.currentThread().getName() + " готов к фазе 1");
barrier.await();
// работа после барьера
System.out.println(Thread.currentThread().getName() + " завершил фазу 1");

// Вторая итерация — барьер сброшен автоматически
System.out.println(Thread.currentThread().getName() + " готов к фазе 2");
barrier.await();
System.out.println(Thread.currentThread().getName() + " завершил фазу 2");
} catch (InterruptedException | BrokenBarrierException e) {
Thread.currentThread().interrupt();
}
};

for (int i = 0; i < 3; i++) {
new Thread(task).start();
}
}
}


Объяснение:
 CountDownLatch спроектирован как одноразовый "затвор". Его внутренний счетчик не имеет метода reset(), и после достижения нуля состояние фиксируется. Это сделано для простоты и производительности в сценариях "один раз дождаться завершения". CyclicBarrier же имеет встроенный механизм сброса: когда последний поток достигает барьера, все освобождаются, и барьер автоматически перезапускается. Он также предоставляет метод reset() для ручного сброса в случае ошибок. CyclicBarrier поддерживает опциональное барьерное действие, которое выполняется перед освобождением потоков — это удобно для агрегации промежуточных результатов.

Для более сложных сценариев с динамическим числом потоков или многофазной синхронизацией лучше использовать Phaser, который позволяет регистрировать и дерегистрировать стороны во время выполнения.


#Java #советы
👍4