CompletableFuture
уже здесь
Дмитрий Чуйко
dmitry.chuyko@oracle.com
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved.
Содержание
Введение
API
Накладные расходы
Пример. Rest-сервис
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 2/45
Safe Harbor Statement
The following is intended to outline our general product direction. It
is intended for information purposes only, and may not be
incorporated into any contract. It is not a commitment to deliver any
material, code, or functionality, and should not be relied upon in
making purchasing decisions. The development, release, and timing
of any features or functionality described for Oracle’s products
remains at the sole discretion of Oracle.
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 3/45
Введение
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 4/45
Параллелизм в Java: *Отступление
∙
JDK 7 EOL
∙
JDK 8u
∙
JDK 9 EA
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 5/45
Параллелизм в Java: История
∙
Threads
– Monitors
– Locks and other primitives
∙
Executors
– Runnable<T>, Callable<T> → lambdas
∙
Future<T>
∙
ForkJoinPool
∙
stream.parallel()
∙
Explicit → implicit
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 6/45
Параллелизм в Java: Future<T>
∙
Обёртка для результата, доступного в будущем
∙
Получение значения требует проверки исключений
– ExecutionException содержит исходное исключение
∙
Исполняется в каком-то потоке и блокирует какой-то
(другой) поток
∙
Можно проверить, доступно ли уже значение
∙
Можно отменить вычисление
Future f = executor.submit (() -> ...);
result = f.get (); // love to be BLOCKED here
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 7/45
Сложности: Обработка ошибок
try {
try {
return parse(fileObject , content.get ());
} catch ( ExecutionException e) {
unfold(e);
}
} catch ( IOException e) {
log.error(e, fileObject );
} catch ( InterruptedException e) {
throw new RuntimeException (e);
}
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 8/45
Сложности: Обработка ошибок
private static void unfold( ExecutionException e) throws IOException ,
InterruptedException {
Throwable cause = e.getCause ();
if (cause instanceof ExecutionException )
unfold (( ExecutionException ) cause );
if (cause instanceof IOException )
throw ( IOException) cause;
if (cause instanceof InterruptedException )
throw ( InterruptedException ) cause;
if (cause instanceof Error)
throw (Error) cause;
if (cause instanceof RuntimeException )
throw ( RuntimeException ) cause;
throw new RuntimeException (e);
}
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 9/45
Сложности: Давайте добавим обработчики!
readFileAsync (file ,
content -> System.out.println(content),
ex -> ex. printStackTrace ();
);
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 10/45
Сложности: Давайте добавим обработчики!
readFileAsync (file ,
content -> System.out.println(content),
ex -> ex. printStackTrace ();
);
∙
↓Добро пожаловать сюда↓
http://callbackhell.com/
readFileAsync (file ,
content -> processContentAsync (content ,
c -> System.out.println(c),
e -> e. printStackTrace ()
);
ex -> ex. printStackTrace ();
);
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 10/45
Сложности: Результат
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 11/45
CompletableFuture: Боремся с вложенностью
CompletableFuture . supplyAsync (() -> readFile(file ))
. thenComposeAsync (content -> processContent (content ))
. whenComplete ((result , ex) -> {
if (ex == null) {
System.out.println(result );
} else {
ex. printStackTrace ();
}
});
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 12/45
CompletableFuture: Композиция
∙
Method chaining
– Нет блокирующих вызовов
– Знакомо и удобно (builders, mocks, streams)
∙
Работаем с несколькими CF
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 13/45
API
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 14/45
Что за класс: CompletableFuture<T>
∙
Core library class since Java SE 8
∙
implements Future<T>
∙
implements CompletionStage<T>
– Элемент композиции
– Вычисление функции
– Связь через результаты
– Методы преобразований
– toCompletableFuture()
∙
Асинхронные операции
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 15/45
Методы: Создание
∙
CompletableFuture()
– boolean complete(T value), успешно только для одного потока
– boolean completeExceptionally(Throwable ex)
∙
CompletableFuture<U> completedFuture(U value)
∙
CompletableFuture<U>
supplyAsync(Supplier<U> supplier [, Executor executor])
∙
CompletableFuture<Void>
runAsync(Runnable runnable [, Executor executor])
∙
ForkJoinPool.commonPool() по умолчанию
– если выключен, new Thread()
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 16/45
Методы: Создание
CompletableFuture <Long > cf1 = CompletableFuture . supplyAsync (() -> 42L);
CompletableFuture <Long > start = CompletableFuture . completedFuture (42L);
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 17/45
Методы: *Отступление
Упрощённая запись generics
∙
Function<? super T,? extends U>
→ Function<T,U>
∙
Consumer<? super T> → Consumer<T>
∙
. . .
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 18/45
Методы: Трансформации
∙
CompletableFuture<U> thenApply(Function<T,U> fn)
– Нет "Async"→ продолжаем в том же потоке
∙
CompletableFuture<U>
thenApplyAsync(Function<T,U> fn [, Executor executor])
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 19/45
Методы: Трансформации (map)
CompletableFuture <Long > cf2 = CompletableFuture
.supplyAsync (() -> 42L)
.thenApply(r1 -> r1 + 2015);
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 20/45
Методы: Подписка
∙
CompletableFuture<Void> thenAccept(Consumer<T> block);
∙
CompletableFuture<Void> thenRun(Runnable action);
∙
Async versions
CompletableFuture <Void > cf3 = CompletableFuture
.supplyAsync (() -> 42L)
.thenApply(r1 -> r1 + 2015)
.thenAccept(System.out:: println );
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 21/45
Методы: Обработка ошибок
∙
CompletableFuture<T>
exceptionally(Function<Throwable, T> fn)
∙
CompletableFuture<U>
handle(BiFunction<T, Throwable, U> fn)
∙
Ошибка пробрасывается по цепочкам
CompletableFuture . supplyAsync (() -> readFile(file ))
. thenComposeAsync (content -> processContent (content ))
.thenAccept(System.out:: println)
. exceptionally (Throwable :: printStackTrace );
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 22/45
Методы: Обработка ошибок
CompletableFuture <Void > cf = new CompletableFuture < >();
cf. completeExceptionally (new RuntimeException ());
//cf. completeExceptionally (new CompletionException (new RuntimeException ()));
cf. exceptionally (e -> {
System.out.println(e);
return null;
});
cf.thenApply(Function.identity ()). exceptionally (e -> {
System.out.println(e); // CompletionException : RuntimeException - not this stage
return null;
});
cf.get (); // ExecutionException : RuntimeException
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 23/45
Методы: Комбинация (reduce)
∙
CompletableFuture<V>
thenCombine (CompletionStage<U> other,
BiFunction<T,U,V> fn)
CompletableFuture <Long > cf2 = CompletableFuture
.supplyAsync (() -> 42L)
.thenCombine ( CompletableFuture . supplyAsync (() -> 2015) , Math ::min);
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 24/45
Методы: Для набора
∙
CompletableFuture<Object>
anyOf(CompletableFuture<?>... cfs)
∙
CompletableFuture<Void>
allOf(CompletableFuture<?>... cfs)
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 25/45
Методы: Композиция (flatMap)
∙
CompletableFuture<U>
thenCompose(Function<T,CompletableFuture<U>> fn)
CompletableFuture <Long > cff = CompletableFuture
.supplyAsync (() -> 42L)
.thenCompose (x -> CompletableFuture .supplyAsync (() -> x + 2015));
CompletableFuture <CompletableFuture <Long >> cff = CompletableFuture
.supplyAsync (() -> 42L)
.thenApply(x -> CompletableFuture . supplyAsync (() -> x + 2015));
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 26/45
Методы: Get
∙
T get() throws InterruptedException, ExecutionException
∙
T get(long timeout, TimeUnit unit) throws
InterruptedException, ExecutionException, TimeoutException
∙
T getNow(T valueIfAbsent)
∙
T join()
– Нет checked exceptions (CompletionException)
...
stream.map(x -> CompletableFuture ...). map( CompletableFuture :: join)
...
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 27/45
Методы: Get
// parallel where?
stream.parallel ()
.map(x -> CompletableFuture .supplyAsync ...)
.map( CompletableFuture :: join );
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 28/45
Методы: Get
// parallel where?
stream.parallel ()
.map(x -> CompletableFuture .supplyAsync ...)
.map( CompletableFuture :: join );
// NOT Executors. newSingleThreadExecutor ();
ExecutorService es1 = new ForkJoinPool (1);
Future <?> task1 = es1.submit (() -> {
try {
es1.submit (()-> System.out.println("1")). get ();
} catch (Exception e) {
}
});
task1.get ();
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 28/45
Методы: Get
// parallel where?
stream.parallel ()
.map(x -> CompletableFuture .supplyAsync ...)
.map( CompletableFuture :: join );
// NOT Executors. newSingleThreadExecutor ();
ExecutorService es1 = new ForkJoinPool (1);
Future <?> task1 = es1.submit (() -> {
try {
es1.submit (()-> System.out.println("1")). get ();
} catch (Exception e) {
}
});
task1.get ();
// parallel where?
CompletableFuture . supplyAsync (() -> stream (). parallel ()... , fjpN );
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 28/45
Методы: Исполнение в потоках
∙
isDone() → исполнение метода в текущем потоке
– Если не ...Async()
– И для exceptionally()
∙
helpPostComplete() на любой чих помогаем будить ждущих
– И для exceptionally()
– И для повторных вызовов complete()
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 29/45
Накладные расходы
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 30/45
Бенчмарк: Окружение
∙
Intel Core i5-3320M (1x2x2, 3.3 GHz)
∙
Linux x64 (kernel 3.19)
∙
JDK 9 EA (b64)
∙
OpenJDK JMH 1.10-SNAPSHOT
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 31/45
Бенчмарк: Базовые операции
@Param ({ "1024" })
public volatile int loada;
@Param ({ "1024" })
public volatile int loadb;
Integer a() {
Blackhole.consumeCPU(loada );
return loada;
}
Integer b() {
Blackhole.consumeCPU(loadb );
return loadb;
}
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 32/45
Бенчмарк: Что сравниваем
Простой вариант
@Benchmark
public Integer ab() {
return a() * b();
}
@Benchmark
public Integer stream () throws InterruptedException , ExecutionException {
return IntStream.range (0, 2)
.mapToObj ((i) -> i == 0 ? a() : b())
.reduce (1, (a, b) -> a * b);
}
@Benchmark
public Integer parstream () throws InterruptedException , ExecutionException {
return IntStream.range (0, 2). parallel ()
.mapToObj ((i) -> i == 0 ? a() : b())
.reduce (1, (a, b) -> a * b);
}
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 33/45
Бенчмарк: Что сравниваем
Future
@Benchmark
public Integer future2 () throws InterruptedException , ExecutionException {
ExecutorService fjp = ForkJoinPool .commonPool ();
Future <Integer > fa = fjp.submit (() -> a());
Future <Integer > fb = fjp.submit (() -> b());
return fa.get() * fb.get ();
}
@Benchmark
public Integer future3 () throws InterruptedException , ExecutionException {
ExecutorService fjp = ForkJoinPool .commonPool ();
Future <Integer > fa = fjp.submit (() -> a());
Future <Integer > fb = fjp.submit (() -> b());
return fjp.submit (() -> fa.get() * fb.get ()). get ();
}
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 34/45
Бенчмарк: Что сравниваем
CompletableFuture
@Benchmark
public Integer cf2() throws InterruptedException , ExecutionException {
return CompletableFuture . supplyAsync (() -> a())
.thenCombine ( CompletableFuture . supplyAsync (() -> b()), (a, b) -> a * b)
.get ();
}
@Benchmark
public Integer cf3() throws InterruptedException , ExecutionException {
return CompletableFuture . supplyAsync (() -> a())
. thenCombineAsync ( CompletableFuture .supplyAsync (() -> b()), (a, b) -> a * b)
.get ();
}
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 35/45
Бенчмарк: Результаты
Параметры по умолчанию (loada=loadb=1K)
Вариант 𝜇c/оп
ab 6 ± 1
cf2 4 ± 1
cf3 4 ± 1
future2 8 ± 1
future3 8 ± 1
parstream 7 ± 1
stream 6 ± 1
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 36/45
Бенчмарк: Результаты
Оценка пустой операции (loada=loadb=0)
Вариант Время, нc/оп Аллокации, B/оп
ab 11 ± 1 0 ± 0
cf2 715 ± 11 200 ± 1
cf3 1060 ± 17 204 ± 2
future2 4733 ± 135 80 ± 1
future3 4657 ± 213 128 ± 1
parstream 421 ± 24 496 ± 1
stream 131 ± 1 248 ± 1
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 37/45
Бенчмарк: Результаты
Долгая операция (loada=loadb=128K)
Вариант 𝜇c/оп
ab 713 ± 1
cf2 383 ± 8
cf3 393 ± 10
future2 386 ± 8
future3 387 ± 9
parstream 378 ± 10
stream 713 ± 1
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 38/45
Пример. Rest-сервис
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 39/45
Сервис: Ингридиенты
∙
JDK 8u25
∙
JAX-RS 2.0
https://jax-rs-spec.java.net/
∙
Jersey RI
https://jersey.java.net/
∙
Grizzly NIO framework
https://grizzly.java.net/
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 40/45
Сервис: Ингридиенты
∙
JDK 8u25
∙
JAX-RS 2.0
https://jax-rs-spec.java.net/
∙
Jersey RI
https://jersey.java.net/
∙
Grizzly NIO framework
https://grizzly.java.net/
∙
CompletableFuture
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 40/45
Сервис: Запускалка
public class Main {
public static final String BASE_URI = "http :// localhost :8080/ jee/";
public static void main(String [] args) throws IOException {
ResourceConfig rc = new ResourceConfig (). packages("com.oracle.demo");
HttpServer server = GrizzlyHttpServerFactory
. createHttpServer (URI.create(BASE_URI), rc);
System.out.println(String.format("Jersey␣app␣started␣"
+ "with␣WADL␣available␣at␣% sapplication .wadln"
+ "Hit␣enter␣to␣stop␣it...", BASE_URI ));
System.in.read ();
server.shutdownNow ();
}
}
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 41/45
Сервис: Endpoint
@Path("jeeconf")
public class JEEConf {
@Inject
DataService dataService ;
// @ManagedAsync -- NOT NEEDED
@GET
@Produces(MediaType.TEXT_PLAIN)
public void asyncGet(@Suspended final AsyncResponse asyncResponse ) {
dataService
. findAudience ()
. thenCombine( dataService. findImpression (), (a, b) -> a + b)
.thenApply( asyncResponse :: resume)
. exceptionally ( asyncResponse :: resume );
// way #1
asyncResponse .setTimeout (1, SECONDS );
asyncResponse . setTimeoutHandler (ar -> ar.resume(new TimeoutException ()));
}
}
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 42/45
Сервис: Provider
Часть 1/2
@ManagedBean
@Path("data")
public class DataService {
// @Inject
ScheduledExecutorService shedPool = Executors. newScheduledThreadPool (1);
public CompletableFuture <String > findAudience () {
return find("audience");
}
public CompletableFuture <String > findImpression () {
return find("impression");
}
@PreDestroy
public void shutdown () {
shedPool.shutdownNow ();
}
...
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 43/45
Сервис: Provider
Часть 2/2
public CompletableFuture <String > find(String path) {
CompletableFuture <String > promise = new CompletableFuture < >();
CompletableFuture
.runAsync (() -> {
try {
promise.complete(new String(Files. readAllBytes (Paths.get(path ))));
} catch ( IOException e) {
promise. completeExceptionally (e);
}
});
// way #2. and impact on shedPool.
shedPool.schedule(
() -> promise. completeExceptionally (new TimeoutException ()), 1, SECONDS );
return promise;
}
}
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 44/45
Сервис: ExceptionMapper
@Provider
public class CompletionExceptionMapper
implements ExceptionMapper <CompletionException > {
public Response toResponse( CompletionException bex) {
return Response.status(Status. BAD_REQUEST)
.entity(new File("error.png")). type("image/png"). build ();
}
}
Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 45/45

CompletableFuture уже здесь

  • 1.
  • 2.
  • 3.
    Safe Harbor Statement Thefollowing is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, and timing of any features or functionality described for Oracle’s products remains at the sole discretion of Oracle. Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 3/45
  • 4.
    Введение Copyright c○ 2015,Oracle and/or its affiliates. All rights reserved. 4/45
  • 5.
    Параллелизм в Java:*Отступление ∙ JDK 7 EOL ∙ JDK 8u ∙ JDK 9 EA Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 5/45
  • 6.
    Параллелизм в Java:История ∙ Threads – Monitors – Locks and other primitives ∙ Executors – Runnable<T>, Callable<T> → lambdas ∙ Future<T> ∙ ForkJoinPool ∙ stream.parallel() ∙ Explicit → implicit Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 6/45
  • 7.
    Параллелизм в Java:Future<T> ∙ Обёртка для результата, доступного в будущем ∙ Получение значения требует проверки исключений – ExecutionException содержит исходное исключение ∙ Исполняется в каком-то потоке и блокирует какой-то (другой) поток ∙ Можно проверить, доступно ли уже значение ∙ Можно отменить вычисление Future f = executor.submit (() -> ...); result = f.get (); // love to be BLOCKED here Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 7/45
  • 8.
    Сложности: Обработка ошибок try{ try { return parse(fileObject , content.get ()); } catch ( ExecutionException e) { unfold(e); } } catch ( IOException e) { log.error(e, fileObject ); } catch ( InterruptedException e) { throw new RuntimeException (e); } Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 8/45
  • 9.
    Сложности: Обработка ошибок privatestatic void unfold( ExecutionException e) throws IOException , InterruptedException { Throwable cause = e.getCause (); if (cause instanceof ExecutionException ) unfold (( ExecutionException ) cause ); if (cause instanceof IOException ) throw ( IOException) cause; if (cause instanceof InterruptedException ) throw ( InterruptedException ) cause; if (cause instanceof Error) throw (Error) cause; if (cause instanceof RuntimeException ) throw ( RuntimeException ) cause; throw new RuntimeException (e); } Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 9/45
  • 10.
    Сложности: Давайте добавимобработчики! readFileAsync (file , content -> System.out.println(content), ex -> ex. printStackTrace (); ); Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 10/45
  • 11.
    Сложности: Давайте добавимобработчики! readFileAsync (file , content -> System.out.println(content), ex -> ex. printStackTrace (); ); ∙ ↓Добро пожаловать сюда↓ http://callbackhell.com/ readFileAsync (file , content -> processContentAsync (content , c -> System.out.println(c), e -> e. printStackTrace () ); ex -> ex. printStackTrace (); ); Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 10/45
  • 12.
    Сложности: Результат Copyright c○2015, Oracle and/or its affiliates. All rights reserved. 11/45
  • 13.
    CompletableFuture: Боремся свложенностью CompletableFuture . supplyAsync (() -> readFile(file )) . thenComposeAsync (content -> processContent (content )) . whenComplete ((result , ex) -> { if (ex == null) { System.out.println(result ); } else { ex. printStackTrace (); } }); Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 12/45
  • 14.
    CompletableFuture: Композиция ∙ Method chaining –Нет блокирующих вызовов – Знакомо и удобно (builders, mocks, streams) ∙ Работаем с несколькими CF Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 13/45
  • 15.
    API Copyright c○ 2015,Oracle and/or its affiliates. All rights reserved. 14/45
  • 16.
    Что за класс:CompletableFuture<T> ∙ Core library class since Java SE 8 ∙ implements Future<T> ∙ implements CompletionStage<T> – Элемент композиции – Вычисление функции – Связь через результаты – Методы преобразований – toCompletableFuture() ∙ Асинхронные операции Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 15/45
  • 17.
    Методы: Создание ∙ CompletableFuture() – booleancomplete(T value), успешно только для одного потока – boolean completeExceptionally(Throwable ex) ∙ CompletableFuture<U> completedFuture(U value) ∙ CompletableFuture<U> supplyAsync(Supplier<U> supplier [, Executor executor]) ∙ CompletableFuture<Void> runAsync(Runnable runnable [, Executor executor]) ∙ ForkJoinPool.commonPool() по умолчанию – если выключен, new Thread() Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 16/45
  • 18.
    Методы: Создание CompletableFuture <Long> cf1 = CompletableFuture . supplyAsync (() -> 42L); CompletableFuture <Long > start = CompletableFuture . completedFuture (42L); Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 17/45
  • 19.
    Методы: *Отступление Упрощённая записьgenerics ∙ Function<? super T,? extends U> → Function<T,U> ∙ Consumer<? super T> → Consumer<T> ∙ . . . Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 18/45
  • 20.
    Методы: Трансформации ∙ CompletableFuture<U> thenApply(Function<T,U>fn) – Нет "Async"→ продолжаем в том же потоке ∙ CompletableFuture<U> thenApplyAsync(Function<T,U> fn [, Executor executor]) Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 19/45
  • 21.
    Методы: Трансформации (map) CompletableFuture<Long > cf2 = CompletableFuture .supplyAsync (() -> 42L) .thenApply(r1 -> r1 + 2015); Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 20/45
  • 22.
    Методы: Подписка ∙ CompletableFuture<Void> thenAccept(Consumer<T>block); ∙ CompletableFuture<Void> thenRun(Runnable action); ∙ Async versions CompletableFuture <Void > cf3 = CompletableFuture .supplyAsync (() -> 42L) .thenApply(r1 -> r1 + 2015) .thenAccept(System.out:: println ); Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 21/45
  • 23.
    Методы: Обработка ошибок ∙ CompletableFuture<T> exceptionally(Function<Throwable,T> fn) ∙ CompletableFuture<U> handle(BiFunction<T, Throwable, U> fn) ∙ Ошибка пробрасывается по цепочкам CompletableFuture . supplyAsync (() -> readFile(file )) . thenComposeAsync (content -> processContent (content )) .thenAccept(System.out:: println) . exceptionally (Throwable :: printStackTrace ); Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 22/45
  • 24.
    Методы: Обработка ошибок CompletableFuture<Void > cf = new CompletableFuture < >(); cf. completeExceptionally (new RuntimeException ()); //cf. completeExceptionally (new CompletionException (new RuntimeException ())); cf. exceptionally (e -> { System.out.println(e); return null; }); cf.thenApply(Function.identity ()). exceptionally (e -> { System.out.println(e); // CompletionException : RuntimeException - not this stage return null; }); cf.get (); // ExecutionException : RuntimeException Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 23/45
  • 25.
    Методы: Комбинация (reduce) ∙ CompletableFuture<V> thenCombine(CompletionStage<U> other, BiFunction<T,U,V> fn) CompletableFuture <Long > cf2 = CompletableFuture .supplyAsync (() -> 42L) .thenCombine ( CompletableFuture . supplyAsync (() -> 2015) , Math ::min); Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 24/45
  • 26.
    Методы: Для набора ∙ CompletableFuture<Object> anyOf(CompletableFuture<?>...cfs) ∙ CompletableFuture<Void> allOf(CompletableFuture<?>... cfs) Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 25/45
  • 27.
    Методы: Композиция (flatMap) ∙ CompletableFuture<U> thenCompose(Function<T,CompletableFuture<U>>fn) CompletableFuture <Long > cff = CompletableFuture .supplyAsync (() -> 42L) .thenCompose (x -> CompletableFuture .supplyAsync (() -> x + 2015)); CompletableFuture <CompletableFuture <Long >> cff = CompletableFuture .supplyAsync (() -> 42L) .thenApply(x -> CompletableFuture . supplyAsync (() -> x + 2015)); Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 26/45
  • 28.
    Методы: Get ∙ T get()throws InterruptedException, ExecutionException ∙ T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException ∙ T getNow(T valueIfAbsent) ∙ T join() – Нет checked exceptions (CompletionException) ... stream.map(x -> CompletableFuture ...). map( CompletableFuture :: join) ... Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 27/45
  • 29.
    Методы: Get // parallelwhere? stream.parallel () .map(x -> CompletableFuture .supplyAsync ...) .map( CompletableFuture :: join ); Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 28/45
  • 30.
    Методы: Get // parallelwhere? stream.parallel () .map(x -> CompletableFuture .supplyAsync ...) .map( CompletableFuture :: join ); // NOT Executors. newSingleThreadExecutor (); ExecutorService es1 = new ForkJoinPool (1); Future <?> task1 = es1.submit (() -> { try { es1.submit (()-> System.out.println("1")). get (); } catch (Exception e) { } }); task1.get (); Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 28/45
  • 31.
    Методы: Get // parallelwhere? stream.parallel () .map(x -> CompletableFuture .supplyAsync ...) .map( CompletableFuture :: join ); // NOT Executors. newSingleThreadExecutor (); ExecutorService es1 = new ForkJoinPool (1); Future <?> task1 = es1.submit (() -> { try { es1.submit (()-> System.out.println("1")). get (); } catch (Exception e) { } }); task1.get (); // parallel where? CompletableFuture . supplyAsync (() -> stream (). parallel ()... , fjpN ); Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 28/45
  • 32.
    Методы: Исполнение впотоках ∙ isDone() → исполнение метода в текущем потоке – Если не ...Async() – И для exceptionally() ∙ helpPostComplete() на любой чих помогаем будить ждущих – И для exceptionally() – И для повторных вызовов complete() Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 29/45
  • 33.
    Накладные расходы Copyright c○2015, Oracle and/or its affiliates. All rights reserved. 30/45
  • 34.
    Бенчмарк: Окружение ∙ Intel Corei5-3320M (1x2x2, 3.3 GHz) ∙ Linux x64 (kernel 3.19) ∙ JDK 9 EA (b64) ∙ OpenJDK JMH 1.10-SNAPSHOT Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 31/45
  • 35.
    Бенчмарк: Базовые операции @Param({ "1024" }) public volatile int loada; @Param ({ "1024" }) public volatile int loadb; Integer a() { Blackhole.consumeCPU(loada ); return loada; } Integer b() { Blackhole.consumeCPU(loadb ); return loadb; } Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 32/45
  • 36.
    Бенчмарк: Что сравниваем Простойвариант @Benchmark public Integer ab() { return a() * b(); } @Benchmark public Integer stream () throws InterruptedException , ExecutionException { return IntStream.range (0, 2) .mapToObj ((i) -> i == 0 ? a() : b()) .reduce (1, (a, b) -> a * b); } @Benchmark public Integer parstream () throws InterruptedException , ExecutionException { return IntStream.range (0, 2). parallel () .mapToObj ((i) -> i == 0 ? a() : b()) .reduce (1, (a, b) -> a * b); } Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 33/45
  • 37.
    Бенчмарк: Что сравниваем Future @Benchmark publicInteger future2 () throws InterruptedException , ExecutionException { ExecutorService fjp = ForkJoinPool .commonPool (); Future <Integer > fa = fjp.submit (() -> a()); Future <Integer > fb = fjp.submit (() -> b()); return fa.get() * fb.get (); } @Benchmark public Integer future3 () throws InterruptedException , ExecutionException { ExecutorService fjp = ForkJoinPool .commonPool (); Future <Integer > fa = fjp.submit (() -> a()); Future <Integer > fb = fjp.submit (() -> b()); return fjp.submit (() -> fa.get() * fb.get ()). get (); } Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 34/45
  • 38.
    Бенчмарк: Что сравниваем CompletableFuture @Benchmark publicInteger cf2() throws InterruptedException , ExecutionException { return CompletableFuture . supplyAsync (() -> a()) .thenCombine ( CompletableFuture . supplyAsync (() -> b()), (a, b) -> a * b) .get (); } @Benchmark public Integer cf3() throws InterruptedException , ExecutionException { return CompletableFuture . supplyAsync (() -> a()) . thenCombineAsync ( CompletableFuture .supplyAsync (() -> b()), (a, b) -> a * b) .get (); } Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 35/45
  • 39.
    Бенчмарк: Результаты Параметры поумолчанию (loada=loadb=1K) Вариант 𝜇c/оп ab 6 ± 1 cf2 4 ± 1 cf3 4 ± 1 future2 8 ± 1 future3 8 ± 1 parstream 7 ± 1 stream 6 ± 1 Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 36/45
  • 40.
    Бенчмарк: Результаты Оценка пустойоперации (loada=loadb=0) Вариант Время, нc/оп Аллокации, B/оп ab 11 ± 1 0 ± 0 cf2 715 ± 11 200 ± 1 cf3 1060 ± 17 204 ± 2 future2 4733 ± 135 80 ± 1 future3 4657 ± 213 128 ± 1 parstream 421 ± 24 496 ± 1 stream 131 ± 1 248 ± 1 Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 37/45
  • 41.
    Бенчмарк: Результаты Долгая операция(loada=loadb=128K) Вариант 𝜇c/оп ab 713 ± 1 cf2 383 ± 8 cf3 393 ± 10 future2 386 ± 8 future3 387 ± 9 parstream 378 ± 10 stream 713 ± 1 Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 38/45
  • 42.
    Пример. Rest-сервис Copyright c○2015, Oracle and/or its affiliates. All rights reserved. 39/45
  • 43.
    Сервис: Ингридиенты ∙ JDK 8u25 ∙ JAX-RS2.0 https://jax-rs-spec.java.net/ ∙ Jersey RI https://jersey.java.net/ ∙ Grizzly NIO framework https://grizzly.java.net/ Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 40/45
  • 44.
    Сервис: Ингридиенты ∙ JDK 8u25 ∙ JAX-RS2.0 https://jax-rs-spec.java.net/ ∙ Jersey RI https://jersey.java.net/ ∙ Grizzly NIO framework https://grizzly.java.net/ ∙ CompletableFuture Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 40/45
  • 45.
    Сервис: Запускалка public classMain { public static final String BASE_URI = "http :// localhost :8080/ jee/"; public static void main(String [] args) throws IOException { ResourceConfig rc = new ResourceConfig (). packages("com.oracle.demo"); HttpServer server = GrizzlyHttpServerFactory . createHttpServer (URI.create(BASE_URI), rc); System.out.println(String.format("Jersey␣app␣started␣" + "with␣WADL␣available␣at␣% sapplication .wadln" + "Hit␣enter␣to␣stop␣it...", BASE_URI )); System.in.read (); server.shutdownNow (); } } Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 41/45
  • 46.
    Сервис: Endpoint @Path("jeeconf") public classJEEConf { @Inject DataService dataService ; // @ManagedAsync -- NOT NEEDED @GET @Produces(MediaType.TEXT_PLAIN) public void asyncGet(@Suspended final AsyncResponse asyncResponse ) { dataService . findAudience () . thenCombine( dataService. findImpression (), (a, b) -> a + b) .thenApply( asyncResponse :: resume) . exceptionally ( asyncResponse :: resume ); // way #1 asyncResponse .setTimeout (1, SECONDS ); asyncResponse . setTimeoutHandler (ar -> ar.resume(new TimeoutException ())); } } Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 42/45
  • 47.
    Сервис: Provider Часть 1/2 @ManagedBean @Path("data") publicclass DataService { // @Inject ScheduledExecutorService shedPool = Executors. newScheduledThreadPool (1); public CompletableFuture <String > findAudience () { return find("audience"); } public CompletableFuture <String > findImpression () { return find("impression"); } @PreDestroy public void shutdown () { shedPool.shutdownNow (); } ... Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 43/45
  • 48.
    Сервис: Provider Часть 2/2 publicCompletableFuture <String > find(String path) { CompletableFuture <String > promise = new CompletableFuture < >(); CompletableFuture .runAsync (() -> { try { promise.complete(new String(Files. readAllBytes (Paths.get(path )))); } catch ( IOException e) { promise. completeExceptionally (e); } }); // way #2. and impact on shedPool. shedPool.schedule( () -> promise. completeExceptionally (new TimeoutException ()), 1, SECONDS ); return promise; } } Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 44/45
  • 49.
    Сервис: ExceptionMapper @Provider public classCompletionExceptionMapper implements ExceptionMapper <CompletionException > { public Response toResponse( CompletionException bex) { return Response.status(Status. BAD_REQUEST) .entity(new File("error.png")). type("image/png"). build (); } } Copyright c○ 2015, Oracle and/or its affiliates. All rights reserved. 45/45