Java SE 8時代の Java EE 7アプリケーション開発

Java SE 8時代の
Java EE 7アプリケーション開発
Yoshio Terada
Java Evangelist
http://yoshio3.com
Twitter : @yoshioterada
#jdt2014_C1
1
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
以下の事項は、弊社の一般的な製品の方向性に関する概要を説明するものです
。また、情報提供を唯一の目的とするものであり、いかなる契約にも組み込むこ
とはできません。以下の事項は、マテリアルやコード、機能を提供することをコミッ
トメント(確約)するものではないため、購買決定を行う際の判断材料になさらない
で下さい。オラクル製品に関して記載されている機能の開発、リリースおよび時
期については、弊社の裁量により決定されます。
Oracleは、米国オラクルコーポレーション及びその子会社、関連会社の米国及びその他の国における登録商標です。
文中の社名、商品名等は各社の商標または登録商標である場合があります。
2
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
今日のアジェンダ
1. はじめに
2. Java 8 の世界
3. Java SE 8 + EE 7
Concurrency Utilities
3
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
今日のアジェンダ
1. はじめに
2. Java 8 の世界
3. Java SE 8 +
Concurrency Utilities
4
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
祝 Java SE 8
正式リリース
2014 年 03 月 18 日
5
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
Java SE 8 新機能
Lambda 式 & Stream API
JavaFX
JavaScript Engine
Compact Profile
Date & Time API
Type Annotation
Java SE 8
2014年03月18日
6
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
今日は
2つのメッセージを
お届けします
7
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
今日のアジェンダ
1. はじめに
2. Java 8 の世界
3. Java SE 8 + EE 7
Concurrency Utilities
8
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
今後 10 年
500億のデバイス
9
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
全てが繋がる
時代へ !!
10
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
Java SE 8 Compact プロファイル
各APIにどのプロファイルで
利用可能か記載されている
参考:https://blogs.oracle.com/jtc/entry/a_first_look_at_compact
11
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
デモ
12
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
これで終わり?!
基調講演でやったよね?
13
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
Java EE 7は ?!
14
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
LEGO(Java SE Embedded) & Java EE 7
WebSocket デモの構成
GlassFish v4.0.1
Java SE8/EE 7
WebSocket
ブラウザ
エンドポイント
15
JSON
JSON
WebSocket
サーバ
エンドポイント
LEGO MindStorms
の操作命令を送信
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
Java SE8
Embedded
JSON
JSON
WebSocket
LEGO
エンドポイント
LEGO MindStorms
の状態情報を送信
ブラウザからLEGOマインドストームを操作
WebSocket でリアムタイム IoT 通信
ブラウザからの命令
前後左右への移動
停止、スピードアップ・ダウン
LEGO からの情報
超音波センサー・データの表示
JSON でデータ送受信し
RMI に比べ低オーバヘッド
16
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
Java SE 8/EE 7
だけで実現
17
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
今後 10 年も Java !!
18
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
今日のアジェンダ
1. はじめに
2. Java 8 + WebSocket
3. Java SE 8 + EE 7
Concurrency Utilities
19
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
より応答の速い
サービスは必要ですか?
20
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
Java EE 7 で追加されたサーバ・サイドの並列処理
Concurrency Utilities for EE
Application Servers
Web/EJB コンテナ
EJB
JSP
Servlet
Java EE 関連機能
(JAX-RS,JavaMail, CDI など)
Java SE
21
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
Runnable
Callable
ManagedExecutor Service
ManagedScheduledExecutorService
Concurrency Utilities for EE
ContextService
ManagedThreadFactory
さて、ここで質問
(これは Java EE ではなく Java SE の質問)
22
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
Java SE 8 時代どこがおかしい?
23
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
そう!!Lambda 式の適用
(() -> 1); Lambda 式に修正したしこれで OK?
24
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
Java SE 8 (Lambda式) 対応も実施
もう問題ない?!
25
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
本当に?!
26
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
これだけだと課題は分からない
もう少し複雑な課題で確認しましょう。
27
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
課題
10個の並列処理タスクを実行し、
その結果、終わった順番に取得して
表示ください。
28
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
10 個の並列タスク実行の実装方針例
1.  固定長のスレッドプールを持つ、ExecutorService を
作成する
2.  ExecutorCompletionService を使用する
3.  結果を格納するリストを作成する
4.  Callableを実装した10 個の並列タスクを実行する
5.  実行結果を取得する
29
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
1. 2. 3. の実装 : 今まで同様の実装
// 1. 固定長スレッドプールを持つ ExecutorService の作成
ExecutorService exec = Executors.newFixedThreadPool(10);!
// 2. 並列処理を実行する際、処理が完了した順に結果を取り出すサービス
ExecutorCompletionService<Integer> execCompService!
= new ExecutorCompletionService<>(exec);!
// 3. 処理結果を格納するリスト
List<Future<Integer>> futures = new ArrayList<>();
30
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
4. タスクの実装 : MyCallable タスクの実装
public class MyCallableTaskImpl implements Callable<Integer> {!
private final int counter;!
public MyCallableTask(int counter) {!
this.counter = counter;!
}!
@Override!
public Integer call() throws Exception {!
int randomValue = (int) (Math.random() * 10000);!
try {!
Thread.sleep(randomValue);!
return counter;!
} catch (InterruptedException ex) {!
logger.log(Level.SEVERE, null, ex);!
return -1;!
}!
}}
31
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
4. 並列タスクの実装と実行
// 並列処理タスクを 10 個作成し実行
for (int i = 0; i < 10; i++) {!
// 並列タスクを別途 MyCallableTask クラスに実装
MyCallableTaskImpl task = new MyCallableTaskImpl(i);!
//タスクを実行し、実行結果をリストに追加
futures.add(execCompService.submit(task));
}
32
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
これからは
Java SE 8の時代
33
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
4. 並列タスクの実装と実行
Java SE 8
// 並列処理タスクを 10 個作成し実行
IntStream.range(0, 10).forEach(i -> {!
futures.add(execCompService.submit(() -> {!
int randomValue = (int) (Math.random() * 10000);!
Thread.sleep(randomValue);!
return i;!
for 文はもう書かない
}));!
CallableをLambdaで実装
});
Lambda & Stream でスッキリ
34
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
5. 実行結果の取得
// 並列処理タスクを 10 個作成し実行
for (Future<Integer> results : futures) {!
try {!
// 処理結果順に結果を取得
Integer result = execCompService.take().get();!
System.out.println(result);!
} catch (InterruptedException | ExecutionException ex) {!
// 例外処理の実装
}!
}
35
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
これからは
Java SE 8の時代
36
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
5. 実行結果の取得
futures.stream()!
.mapToInt(future -> {!
Java SE 8
Collection 操作はStream API
try {!
return execCompService.take().get();!
} catch (InterruptedException|ExecutionException ex) {!
return -1;!
}!
})!
.forEach(System.out::println);
Lambda & Stream でスッキリ
37
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
プログラムの実行
10個のタスクの内、完了順にタスク番号を表示
38
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
Java SE 8 対応も実施
もう問題ない?!
39
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
本当に?!
40
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
キーワードは Blocking
Future#get() で処理をブロック
41
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
メイン・スレッドの実行
並列タスク(作成順)
1
処理時間 : 9秒
2
処理時間 : 1秒
3
処理時間 : 5秒
10
処理時間 : 2秒
後続処理を
ブロック
「後続処理をブロック」 が大きな課題
n
2
10
・・
3
1
LinkedBlockingQueue
42
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
パフォーマンス・応答時間に影響
1
処理時間 : 9秒
n
並列処理
n
並列処理
ブロック
ブロック
ブロック
全てのタスクの結果を受け取るまで
後続の処理を実行する事は不可能
43
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
Java SE 8 から
Future, Callable は古い !!
for 文 禁止令と同様 Callable 禁止
44
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
CompletableFuture
を使いましょう
45
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
CompletableFuture
はJava EE 環境でも利用可能
用途に応じて応答速度が大幅改善
46
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
デモ
47
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
CompletableFuture
59 個のメソッド
48
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
CompletableFuture#supplyAsync()
supplyAsync() は開始ポイントの一つ
java.util.stream.Stream のように実装可能
49
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
CompletableFuture による
ノン・ブロッキングの並列処理 (パイプライン処理)
他
の
処
理
を
実
行
可
能
並列処理の実行
supplyAsync!
runAsync
結果を取得し
次の処理を実行
結果を取得し
(最終)処理を実行
thenAccept!
thenApply!
themCompose!
thenRun
complete!
cancel!
ノン・ブロッキング
isCompletedExceptionally!
exceptionally!
get!
getNow!
whenComplete!
など
50
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
CompletableFuture による
2 つの並列処理の実行結果より新たな処理を実行
CompletableFuture A
CompletableFuture B
51
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
2 結果を取得し
別の処理を実行可能
A.acceptEither(B,**)!
A.acceptBoth(B,**)!
A.applyToEither(B,**)!
A.runAfterBoth(B,**)!
A.runAfterEither(B,**)!
A.thenAcceptBoth(B,**)!
A.thenCombine(B,**)!
各機能ごとに3種類づつ用意
52
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
ご注意:
Java EE 7
Java EE 環境で ForkJoin を使用する
API の使用は非推奨
ExecutorService を指定可能な
メソッドを利用しましょう。
例:CompletableFuture は ExecutorService を利用可能
supplyAsync(Supplier<U> supplier, Executor executor)
thenAcceptAsync(Consumer<? super T> action, Executor executor)
53
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
CompletableFuture を使用した実装例
Java SE 8
CompletableFuture<T> tasks = !
CompletableFuture!
.supplyAsync(Supplier <U> supplier))!
.thenAcceptAsync(Consumer<? super T> action)!
Stream 操作に類似したパイプライン処理
# Stream#filter().map().forEach();
メソッドの実行結果、新たな CompletableFuture を返す
54
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
supplyAsync() の実装について
CompletableFuture<T> tasks = CompletableFuture!
.supplyAsync(Supplier <U> supplier))!
.thenAcceptAsync(Consumer<? super T> action)!
• 
• 
supplyAsync() は Supplier を引数に持つ
Supplier は java.util.function パッケージに
含まれる関数型インタフェース
•  Lambda 式で記述可能
55
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
Lambda 式をいきなり書けない方
final int data = i;!
Supplier<Integer> func = new Supplier<>() {!
@Override!
public Integer get() {!
int randomValue = (int) (Math.random() * 2000);!
mystopThread(randomValue);!
return i;!
}!
インナー・クラスとして実装して考えてみましょう
};!
Supplier は引数が無しの何か値を返す関数だと理解可能
処理を実装した後、結果を返す
56
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
Lambda 式におきかえる
final int data = i;!
Supplier<Integer> func = new Supplier<>() {!
@Override!
public Integer get() -> {!
int randomValue = (int) (Math.random() * 2000);!
mystopThread(randomValue);!
return i;!
}!
};!
メソッドの引数と、メソッドボディ部分以外を削除
引数部分とメソッド・ボディの間に矢印(->)を挿入
57
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
CompletableFuture の実装を修正
final int data = i;!
CompletableFuture<T> tasks = CompletableFuture!
.supplyAsync(() -> {!
int randomValue = (int) (Math.random() * 2000);!
mystopThread(randomValue);!
return data;!
})!
.thenAcceptAsync(Consumer<? super T> action)!
Supplier の内容を supplyAsync() メソッドの引数に記述
58
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
thenAcceptAsync() の実装について
final int data = i;!
CompletableFuture<T> tasks = CompletableFuture!
.supplyAsync(() -> {!
int randomValue = (int) (Math.random() * 2000);!
mystopThread(randomValue);!
return data;!
})!
.thenAcceptAsync(Consumer<? super T> action)!
• 
• 
• 
thenAcceptAsync() は Consumer を引数に持つ
Consumer は java.util.function パッケージに含まれる関数型インタフェース
Lambda 式で記述可能
59
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
Lambda 式をいきなり書けない方
Consumer<Integer> consume = new Consumer<Integer>() {!
@Override!
public void accept(Integer result) {!
System.out.println(result);!
}!
};!
return consume;!インナー・クラスで実装して考えてみましょう
Consumer は引数が一つで何も値を返さない関数だと理解可能
引数で取得した値を元に、別処理を実装
60
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
Lambda 式に置き換える
Consumer<Integer> consume = new Consumer<Integer>() {!
@Override!
public void accept(Integer result) -> {!
System.out.println(result);!
}!
};!
return consume;!
Consumer<Integer> consume = (result) -> {!
System.out.println(result); }};!
return consume;!
型定義などを省略
Consumer<Integer> consume = System.out::println;!
return consume;!
メソッド参照による実装
61
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
CompletableFuture を使用した実装結果
final int data = i;!
CompletableFuture<T> tasks = CompletableFuture!
.supplyAsync(() -> {!
int randomValue = (int) (Math.random() * 2000);!
mystopThread(randomValue);!
return data;!
})!
.thenAcceptAsync(System.out::println)!
並列処理もノン・ブロッキング実装で
より応答時間を高める事ができます
62
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
CompletableFuture 是非ご活用ください
クライアント・サイドの実装では
利用場面は少ないかもしれません。
サーバ・サイドは用途に応じて有用
です。
Java EE 7 環境でも利用可能です。
(ManagedExecutorService)
複雑な並列処理が必要な場合は、
是非、ご活用ください。
63
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
64
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
Graphic Section Divider
65
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
66
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.