Skip to content

Commit

Permalink
submit java-advanced-ru/asynchrony
Browse files Browse the repository at this point in the history
  • Loading branch information
hexlet-cli committed Jan 7, 2025
1 parent 534ea9a commit 69e6e7e
Show file tree
Hide file tree
Showing 30 changed files with 780 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .current.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"assignment":"java-advanced-ru/sync-primitives"}
{"assignment":"java-advanced-ru/asynchrony"}
2 changes: 2 additions & 0 deletions java-advanced-ru/asynchrony/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.gradle/
build/
3 changes: 3 additions & 0 deletions java-advanced-ru/asynchrony/.idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions java-advanced-ru/asynchrony/.idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions java-advanced-ru/asynchrony/.idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions java-advanced-ru/asynchrony/.idea/jarRepositories.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions java-advanced-ru/asynchrony/.idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions java-advanced-ru/asynchrony/.idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions java-advanced-ru/asynchrony/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
test:
gradle test

run:
gradle run
69 changes: 69 additions & 0 deletions java-advanced-ru/asynchrony/README.html

Large diffs are not rendered by default.

40 changes: 40 additions & 0 deletions java-advanced-ru/asynchrony/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Асинхронность

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

## Ссылки

* [Класс CompletableFuture – представляет собой отложенный результат асинхронных вычислений](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/util/concurrent/CompletableFuture.html)
* [Класс Files – содержит статические методы для работы с файлами и директориями](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/nio/file/Files.html)

## src/main/java/exercise/App.java

## Задачи

* Создайте асинхронный публичный статический метод `unionFiles()`. Метод должен асинхронно читать содержимое двух файлов, объединять эту информацию и записывать её в третий файл. Метод принимает три аргумента – пути до файлов в виде строки. Первые два аргумента – пути до файлов-источников, третий – путь до итогового файла. Метод может принимать абсолютный и относительный путь до файлов. Если хотя-бы один из файлов-источников не существует, на экран должно выводиться сообщение о возникшем исключении. Если итоговый файл не существует, он должен быть создан. Метод должен возвращать `CompletableFuture<String>`.

```java
CompletableFuture<String> result = App.unionFiles("file1.txt", "file2.txt", "dest.txt");
```

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

* В методе `main()`, используя асинхронный метод `unionFiles()`, прочитайте информацию из двух файлов *src/main/resources/file1.txt* и *src/main/resources/file2.txt* и запишите её в третий файл в этой же директории. Имя файла выберите на своё усмотрение.

* Запустите программу при помощи команды `make run`. Убедитесь, что целевой файл создался и он содержит информацию из двух источников.

### Самостоятельная работа

* В классе `App` создайте асинхронный публичный статический метод `getDirectorySize()`, который считает размеры переданной директории не включая поддиректории. Размер директории складывается из размера всех файлов в директории. Метод должен вернуть `CompletableFuture<Long>`.

```java
CompletableFuture<Long> size = App.getDirectorySize("dir/subdir");
```

* Напишите тесты, проверяющие работу этого метода.

### Подсказки

* Для обработки возникших в асинхронном коде исключений можно использовать метод [exceptionally()](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/util/concurrent/CompletableFuture.html#exceptionally(java.util.function.Function))

* Для того, чтобы независимо друг от друга выполнить две задачи, и затем сделать что-то после их выполнения, можно использовать метод [thenCombine()](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/util/concurrent/CompletableFuture.html#thenCombine(java.util.concurrent.CompletionStage,java.util.function.BiFunction))
31 changes: 31 additions & 0 deletions java-advanced-ru/asynchrony/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
plugins {
id 'application'
id 'com.adarshr.test-logger' version '2.1.1'
}

repositories {
mavenCentral()
}

dependencies {
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.0-M1'
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.8.0-M1'
testImplementation 'org.assertj:assertj-core:3.19.0'
testImplementation 'com.github.stefanbirkner:system-lambda:1.2.0'
}

application {
mainClass = 'exercise.App'
}

test {
useJUnitPlatform()
}

testlogger {
showStandardStreams = true
}

tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
}
80 changes: 80 additions & 0 deletions java-advanced-ru/asynchrony/examples/Example.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
class Example {
public static void main(String[] args) {

// Если нам нужно просто асинхронно выполнить задачу и не нужно ничего возвращать

// В виде лямбды передаём объект Runnable
CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
// Задержка имитирует длительно выполняющуюся задачу
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
System.out.println("Run in separate thread");
});

// Ожидаем окончания работы задачи
future1.get();


// Асинхронный запуск задачи и возврат результата работы

CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
// Задержка имитирует длительно выполняющуюся задачу
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
return "Result of async computation";
});

// Ожидаем окончания работы задачи и получаем результат
String result = future2.get(); // "Result of async computation"

// Комбинирование двух CompletableFuture

// Если одна задача не зависит от другой
// Нужно выполнить две задачи независимо одна от другой и выполнить третью,
// когда предыдущее будут завершены


// Задачи выполняются независимо друг от друга
System.out.println("Retrieving weight");
CompletableFuture<Integer> futureWeight = CompletableFuture.supplyAsync(() -> {

try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
throw new IllegalStateException(e);
}
return 100;
});

System.out.println("Retrieving volume");
CompletableFuture<Integer> futureVolume = CompletableFuture.supplyAsync(() -> {

try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
throw new IllegalStateException(e);
}
return 2;
});

// выполняется после завершения первых двух
System.out.println("Calculate density");
CompletableFuture<Integer> futureDensity = futureWeight.thenCombine(futureVolume, (weight, volume) -> {
Integer density = weight / volume;
return density;

// Обработка исключений
// Если при работе задач возникли исключения
// их можно обработать в методе exceptionally
}).exceptionally(ex -> {
System.out.println("Oops! We have an exception - " + ex.getMessage());
return null;
});
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading

0 comments on commit 69e6e7e

Please sign in to comment.