タグ: Java

Jakarta Commons CLI

  • Jakarta Commons CLI
    • コマンドライン引数をパースしてというCLI(Command Line Interface)
    • Options: 受け取れるオプション
    • addOptionで受け取れる引数を追加していく
    • parser.parse(options, args)とするとパースした結果を得られる

phax/ph-cssを使う

phax/ph-css の使い方

b080e264-d67f-11e4-845e-c1f3fdff6678

便利

Immutable パターン

結城先生のデザパタ本マルチスレッド編 第2章のまとめ

問題

複数のスレッドがインスタンスを共有しているが、インスタンスの状態は変化しない。
このときに、何も考えず Single Threaded Execution パターンを使うとスループットが落ちてしまいます。

解決方法

インスタンスが状態変化しないのであれば Single Threaded Execution パターンを使う必要はありません。
その場合は意図しない状態変化を防ぐためにフィールドが変化しないようにする Immutable パターンを用います。
不変性を保つのは大変なので、気をつけて実装する必要があります。またドキュメントにクラスが不変であることを明示する方が良いでしょう。

関連するパターン

  • 状態を変更するスレッドが参照するスレッドの数よりも少ないときは、Read-Write Lock パターンが使えます

コード例はあまりにもつまらないので割愛

適用可能性

  • インスタンスの生成後、状態が変化しない時
  • インスタンスが共有され、頻繁にアクセスされるとき

余談

mutable なクラスと immutable なクラス

Java 標準ライブラリには mutable なクラスと immutable なクラスが対になっているものがある。

  • java.lang.String
  • java.lang.StringBuffer

不変性を守るために

  • フィールドの保持している mutable なインスタンスをそのまま返すようなことをすると不変性が破られる可能性がある
  • コンストラクタに引数として渡したインスタンスをそのままフィールドに代入した場合、不変性が破られる可能性がある

Single Threaded Executionパターン

結城先生のデザパタ本マルチスレッド編 第1章のまとめ

問題

複数のスレッドがインスタンスを共有している状態で、
それぞれのスレッドがインスタンスの状態を勝手に変更すると、インスタンスの安全性が失われます。

解決方法

そこで、そのままではインスタンスが不定な状態に陥ってしまう範囲を定めます。
これをクリティカルセクションと呼びます。
このクリティカルセクションを synchronized を用いて1つのスレッドだけが実行できるようにガードします。
このようなパターンを Single Threaded Execution パターンと呼びます。

関連するパターン

  • インスタンスの状態が変化しないときには Immutable パターンを使うことにより、スループットを向上させることができる
  • インスタンスの状態を参照するスレッドと変更するスレッドが分かれている場合は Read-Write Lock パターンを使うことにより、スループットを向上させることができる

以下のようなカウンターがあったとします

これを次のように複数のスレッドから呼び出すとおかしなことが起こります

実行すると同じ値がログ出力されたり、
300回 increment が呼び出されているはずなのに、最後のログ出力が 300 になっていなかったりするはずです。
increment はインスタンス内部の状態を変化させるメソッドであり、複数のスレッドから呼び出すと予期せぬ挙動をとります。
この部分をクリティカルセクションとして保護してあげれば良いでしょう。単に synchronized をつければよいだけです。

パフォーマンスのために、一般にクリティカルセクションは小さく保つほうが良いでしょう。

適用可能性

  • 複数のスレッドからクラスへのアクセスが行われるとき
    • シングルスレッドで実行するプログラムにはこのような対応は必要ない。
  • クラスが状態変化する可能性を持っているとき
  • 安全性を保つ必要があるとき

余談

long と double はアトミックに扱われない

Javaのprimitive型の参照や代入は基本的にアトミックです。
しかし、longdouble に関してはアトミックではありません。

例えば、同じ long フィールドに対して、異なる2つのスレッドから同時に 5678, 1234 という形で代入をおこなったとします。
するとこのフィールドがどのような値をとるか保証されません。この場合は synchronized を使うか volatile キーワードを使うという手があります。

まとめると

  • 基本型・参照型の参照・代入はアトミック
  • long, double に関しては例外
  • long, double をスレッド間で共有する場合は synchronizedvolatile を使う

計数セマフォ

synchronized を使うと、ある領域を1つのスレッドのみが実行できるように制限できますが、
n個のスレッドのみが実行できるようにしたいなどという場合には計数セマフォというものが用意されている。

使い方は簡単で次のような感じ

Java言語で学ぶデザインパターン 〜マルチスレッド編〜 読書メモ (1)

結城先生のデザパタ本マルチスレッド編がサクッと読めそうだったので読み進めているので、自分用メモ。ほとんど知っている内容ではあったけど、体系的に知識が入っていなかったので、よい確認になる…。

Java 言語のスレッド

スレッドの起動方法

スレッドを起動する方法は2つある

  1. Thread クラスのサブクラスのインスタンスを使ってスレッドを起動する
  2. Runnable インターフェースの実装クラスのインスタンスを使ってスレッドを起動する

それぞれ run() メソッドを実装している。これらを直接呼び出した場合、呼び出したスレッドで処理が実行される。別のスレッドで実行させたい場合は、start() を呼び出す必要がある。以下のテストを実行すると、run() の呼び出しはメインスレッドから行なわれているのが観測できる。

スレッドの生成には ThreadFactory なるものを使うこともできる。これにより Threadnew せずに済む。

Thread の排他制御

  1. synchronized メソッドを使う
  2. synchronized ブロックを使う

あるスレッドから synchronized インスタンスメソッドが呼ばれている間は、
他のスレッドは同じインスタンスの synchronized メソッドを呼び出すことができない。
非 synchronized インスタンスメソッドについては問題なく呼び出すことができる。
ロックはインスタンスごとにされる点に注意。

次の synchronized メソッド と synchronized ブロックを使ったメソッドは等価になります。

また、次の synchronized クラスメソッドと synchronized ブロックを使ったクラスメソッドは等価になります。

スレッドの排他制御をする仕組みを モニタ と呼びます。
また、ロックをとっていることをモニタを所有する、あるいはロックをホールドすると呼ぶこともあります。

スレッドの協調

各インスタンスはウェイトセットという仮想的な概念を持っています。
あるインスタンスがあるスレッドに wait メソッドを呼び出されたとき、インスタンスのウェイトセットにそのスレッドが追加されます。
スレッドは notify, notifyAll, interrupt の呼び出しが発生するか wait のタイムアウトが発生するまで停止します。
synchronized 文やブロックの外側で オブジェクトの wait を呼び出すと IllegalMonitorStateException が発生がスローされます。

スレッドには処理をキャンセルする機能があったり、優先度を設定できたり、スレッドの終了待ちをできたりもする。

マルチスレッドプログラミングの評価基準

  • 安全性(safety): オブジェクトを壊さないこと
  • 生存性(liveness): 必要な処理が行われること
  • 再利用性(reusability): クラスを再利用できること
  • パフォーマンス(performance): 処理を高速・大量に行えること

うち安全性と生存性を守るのは必須

Java8 + AWS Lambda + API Gateway で遊ぶ

 この記事では Java8 で書いたメソッドを AWS Lambda に実行させ、その実行結果を API Gateway を用いて外から取得できるような簡単なアプリケーションを作成していきます。

 めっちゃ雑にいうと、Java で String を返すメソッドを書いて、その文字列を返すAPIを作るというようなことをやります。

 この際、String を返す Java のコードを実行するのが、AWS Lambda の役割で、その実行結果を取得できるエンドポイントを提供するのが API Gateway の役割になります。

 また、ちょっと手を加えるだけで簡単に JSON を返す API を作ることもできるので、使い方次第では遊べるツールになるのではないでしょうか?

固定した文字列を返すAPIを作成する

 まず、あるエンドポイントを叩くと、ただ文字列が帰ってくるだけのAPIを作成しながら、AWS LambdaAPI Gateway の使い方を確認していきます。

Gradleプロジェクト作成〜実行対象のメソッド作成

 gradleで適当にプロジェクトを作成してください。手元で実際に使った build.gradle ファイルは以下のような具合です。

 続いて、AWS Lambda で実行する対象のメソッドを作成します。めっちゃ簡単なので「馬鹿にしてんのか!」って思うかもしれませんが、まあチュートリアルですので…。

あとはプロジェクトルートから ./gradlew builde を叩いて build/libs 以下にできた jarAWS Lambda にアップロードするだけ!めっちゃ簡単じゃないですか?

AWS Lambda への jar のアップロードと実行

以下のように進めてください

1. AWSのマネジメントコンソールから Lambda を探してクリックします
2. create a lambda function ボタンをクリック
3. 適当なテンプレート一覧が出てくるが、スルーして右下の skip をクリック
4. Name を適当に埋め、Runtimejava8 を選択
5. zip をアップロードできるようになるので、さっき作った jar を選択する
6. Handlerのところにはさっき作ったメソッドを指定。上の例だと com.github.gochiusa.lambda.routes.api.v1.text.Words::get という感じで {package}.{class}::{method} という感じでしていすれば良い。残りの項目も適当に埋める。

適当にすすめると、左上に test というボタンが出てくるので押せば、晴れて AWS Lambda上 で、自分が書いた Java8 コードが実行されてくれる。だいぶ説明を端折っているので詳しくは AWS のドキュメントを見ればいいと思います。

API Gateway でエンドポイントを作る

マネジメントコンソールから API Gateway へ行き、create API をクリック

スクリーンショット 2016-02-28 0.40.49

API の名前を適当につけ先に進む

スクリーンショット 2016-02-28 0.40.57

create Method をクリックする

スクリーンショット 2016-02-28 0.44.14

以下のような感じで適当に各フィールドを埋める。ここで指定する lamda resion はさっき作った lamda function が置いてあるリージョンを指定。lambda function は作ったやつの名前を入れる。

スクリーンショット 2016-02-28 0.41.53 1

以上がおわったら Save を押して、Deploy API のほうに進めば、"ご注文はうさぎですか?" とだけ返してくれる最高なAPIが出来上がる。

JSON を返す API を作る

 JSON を返す lambda function も簡単につくれます。AWS Lambda は、POJO を返す Lamda function を実行すると JSON のレスポンスに変換してくれるみたいでめっちゃ楽しそうです。具体的にはこんなAPIがつくれます。

まずは、上記の感じ構造を持った POJO を定義しましょう。

んであとは、関数の戻り型、戻り値をこいつにしてやればOKです。

ソースコードはここにまとめて置いてあるのでまあ適当に見ていただければ…。

おわりに

 AWS Lambda で Java のコード動かしている記事があんまりなかったので書いたが、だいぶ雑なので迷ったらドキュメントか、他の優しい人が書いた記事を読むと良いと思います。AWS Lambda と API Gateway、どちらも素晴らしいサービスですね。どんどん活用していきたい…。

謝辞など…

 実はWantedly さんでやっていた Serverless Framework の勉強会に参加させていただき、この周辺のものに触れることができました。Wantedlyさん、ありがとうございます…。この記事の内容に近いもののハンズオンでしたので、AWS LambdaやAPI Gatewayに初めて触る方は、まずそちらを試して見ると良いと思います。

Scalaのtraitを解剖してみた

Scalaのtraitを解剖してみた

これを jad すると

こうなりました

String Interpolationについては以下のスライドが詳しいです

Scalaの末尾再帰除去を確認する

Scalaの末尾再帰除去を実際にjadを使って確かめただけの簡単な記録。 jadの導入は以下のとおり。

簡単な階乗関数で確認すればわかりやすい

こんなのをコンパイルして jad でどうなっているか確認します。以下その結果。

factはそのまんま、fact2はちゃんと末尾再帰除去されている様子が見て取れます

Javaではどうなのか

Javaで同じことをしてみる

こいつは以下のような残念な結果に

こいつをどうするかについては次のURLが詳しい

Javaでオートマトンを作ろう

「機械」は何をしているのだろうか

 たとえば照明のスイッチについて、消えている状態に対してOFFボタンを押しても何も起こりません。ONボタンを押すと点灯状態になります。逆に照明がついている状態に対して、OFFボタンを押すと消え、ONボタンを押しても何も起こりません。図にまとめるとこんな感じです。

automaton

 このように「ある状態に対して入力を与えたとき、どんなふうに振る舞うかということ」は、様々な機械のしていることの本質のひとつであると言うことができると思います。このモデルのことを状態機械(State Machine)、あるいはオートマトン(automaton)と呼びます。

 現在私たちが用いているパソコンやモバイル端末などは、尋常でない数のシステムがくみ合わさって実現されています。しかしながら上記の図くらい機械というものを抽象化すれば、人間の脳みそでも全容を理解しながら追っていくことができます。

機械とオートマトン

 様々な機械は、ほとんどの場合ある目的のために作られていると思います。その目的に達した状態を終了状態(end state)、あるいは受容状態(accept state)と呼ぶことにしましょう。逆に機械を動かす前の状態を開始状態(start state)と呼ぶことにしましょう。機械は、開始状態か受容状態を区別できる1ビットの出力を生成できるものとします。

 たとえば先ほどの照明の例では、最初の状態は消灯している状態でしょう。機械になんらかの入力を与えて、照明が点灯している状態が終了状態になると思います。これを図で表現すると以下のようになります。開始状態には矢印をつけ、終了状態には二重の円を用います。

automaton-1

 さて、このオートマトンは有限個の状態と遷移の組み合わせからなっていることは分かると思います。この場合、有限オートマトン(Finite Automaton)と呼ぶことができます。さらに次にどの状態になるか確実に決まっていることもわかります。これを決定性有限オートマトン(DFA: Deterministic Finite Automaton)と言います。

Javaで決定性有限オートマトン

 まずはこの決定性有限オートマトンをJavaで書いてみましょう。今回作るオートマトンが取りうる状態は {ON, OFF} の2つ、受け付ける入力は {0, 1} の2つにします。0 が入力されたら必ず OFF に 1 が入力されたら必ず ON の状態に遷移することにします。まとめると次の図のようになります。

automaton-2

 このオートマトンは 1 が入力されると受容状態に達する、つまり受理されて、 0 が入力されると受理されないという代物です。

 さてコーディングにとりかかります。今回は凝ったことはやらずに、状態を列挙体State、状態から状態への遷移規則をRuleクラス、遷移規則をまとめたものをRuleBookクラス、オートマトンをDFAクラスとして以下のように書き下してみました。

 ここまでできたら利用側のコードを書いて動かしてみます。まずは状態の遷移規則を表すRuleをまとめたRuleBookのインスタンスを用意。次に受容状態を表すセットを準備します。最後にDFAクラスに開始状態と受容状態のセットと遷移規則集を渡してインスタンス生成をしたら、inputメソッドでいろんな入力を与えて挙動を確認できます。

 残念ながらこのコードは汎用的ではありませんが、何となく有限オートマトンの雰囲気はつかめたのではないでしょうか。

非決定性有限オートマトンの導入

 実際の機械は遷移が必ずしも成功するとは限りません。あるいは何も入力していなくても遷移してしまうことがあるかもしれません。こうしたことをモデルに組み込むためには、「次にどの状態に遷移するか確実に決まっている性質」である決定性を捨てる必要があります。これを非決定性有限オートマトン(NFA: Nondeterministic Finite Automaton)と言います。

 たとえば先ほどの照明の例に対して、消灯状態から 1 を与えたとき、点灯するかもしれないし、しないかもしれないということが表現できるようになります。図にすると以下のような具合です。

automaton-3

 このとき、受理状態になるなんらかのパスがあれば、その入力は受理されると考えることにしましょう。つまり、1 や 11 や 011 などは全て受理されます。 0 や 000 や 000000 は受理されません。

 これができると何が嬉しいのか、少し考えてみることにします。今回は「最後から2番目の入力が 1 である数字の列を受理する機械」を考えてみましょう。これを決定性有限オートマトンの枠組みで考えるのは難しいと思います(実際に考えてみてください)。これがもし「最初から2番目の入力が 1 である数字の列を受理する機械」であれば以下のように決定性有限オートマトンとして簡単に表現が思いつくでしょう。

automaton3-1

 では、先ほど導入した非決定性有限オートマトンの枠組みで「最後から2番目の入力が 1 である数字の列を受理する機械」を表現するとどうなるのでしょうか。以下の図のようになります。

automaton4-2

 例えば 10, 00010, 01010101010 などは受理される(=受容状態へのパスが存在する)ことがわかります。 01 や 1001 などは受理されないことも分かります。

Javaで非決定性オートマトン

 さて、実際にJavaで実装してみましょう。先ほどよりやや汎用的に使えるように、状態をState、遷移規則をRule、遷移規則集をRuleBookとして以下のようなコードを用意します。

 そして非決定性有限オートマトンをNFAクラスとして次のように定義します。isAcceptableメソッドは入力から得られる可能性のある全ての状態のSetを作って、その中に受容状態があるかどうかを返します。こうすることにより、受容状態へのパスがあるかどうかを調べています。

 最後に利用側のクラスの例として、テストコードを掲載しておきます。

 実装的に雑な部分は目立つと思いますが、おおむね非決定性有限オートマトンと入力を受容するかどうかを判定するアルゴリズムについては理解頂けたかと思います。

自由移動

 長さが2の倍数の文字列を受理する機械は次のように簡単に表現できます。

automaton4-4

 では、長さが2か3の倍数の文字列を受理する機械は果たしてどうしたら良いでしょうか。ここで自由移動(free move)という規則を導入すると簡単に表現ができます。これは何の入力もなしに従うことができる規則です。これを用いると以下のように表現できます。

automaton4-3

 図中の1 -> 2,1 -> 3 は何の入力もなしに遷移が可能です。こうすることにより 00, 000, 0000, 000000 などは受理され、0, 00000などは受理されないことが分かると思います。

 一見、オートマトンは単純で何の役にも立たなそうにみえますが、身近でかつ重要なところでは正規表現などに使われています。また、生物や人工知能の分野では神経系をオートマトンを応用した形でモデル化して様々な研究が行われていたりします。

他クラスに依存しないテストを支える仕組み:スタブ・モック・スパイ

手元にはあったが長らく積んでいたJUnit実践入門の11章:テストダブルの章を読んでまとめを書きました.実際のところMockitoってなんだかいままでよく分からない存在だったけど,手をつけてみるとかなりお手軽&便利なものでした.学習コストもそれほど高くないので,何となく敬遠していたり,テストってどう書けば良いのかよくわかっていない私のような人がいたら是非,Mockitoを使ったテストコードを実際に書いてみることをお勧めします.

テスト対象クラスが依存するクラス・モジュール問題

理想的なユニットテストは,依存するすべてのクラスや外部システムを使用したもの  
* なぜなら,実際に動くコードはそういう状況で動くのだから
* しかし依存する本物のオブジェクトを常に使用できるとは限らないし,ユニットテストで扱いにくいオブジェクトもある
* このようなときにテストしやすいようにリファクタリングしたり,本物のオブジェクトの代役となるオブジェクトに置き換えてテストを行うという手法が用いられる

テスタビリティを高めるリファクタリング

  • JavaのDateの精度はミリ秒であるため次のコードは,テストに成功したり失敗したりする
  • 乱数を使ったコードは当然ながらテストが書きにくい
  • このようにインスタンス生成のタイミングや環境に依存してしまう部分が含まれるコードのテストは難しい

インスタンス生成の部分を抽出してファクトリメソッドを作ると,ここをOverrideして振る舞いを変えることができ,依存度を下げることができる

今回の例に対してはやや過剰な実装とはなるが,振る舞いの複雑なメソッドをオブジェクトに切り出し,委譲を使って差し替え可能にするという方法もある

テストダブル:スタブ/モック/スパイ

  • テスト対象となるクラスが他クラスに依存していないケースはほとんどない
  • 依存しているクラスもまた他のクラスに依存している
  • この状態でテストを行うメリットは実行時に近い状態でテストができること
  • デメリットはテスト対象以外の問題を原因としてテストが失敗する可能性があること
  • このとき依存しているオブジェクトの代役(スタブ・モック)を使うことをテストダブルという

スタブ

  • スタブとは依存するクラスやモジュールとして代用できる仮のクラス・モジュール
  • 以下のようなときに用いられる
    • 依存オブジェクトが予想できない振る舞いを持つとき
    • 依存オブジェクトのクラスがまだ存在しないとき
    • 依存オブジェクトの実行コストが高く,簡単に利用できない
    • 依存オブジェクトが実行環境に強く依存している
  • 例えば乱数を用いるようなクラスのテストは,依存オブジェクトRandomが予想できない振る舞いを持つためスタブを使うと良い
  • コード的には次のようなものになる

モック

  • スタブと同様にテスト対象が依存するクラスやモジュールの代用として使用されるもの
  • スタブはメソッドの返り値を予想可能な値にすることにより、依存クラス・モジュールが正しく利用できているか確かめるもの
  • モックはメソッドが正しく呼び出されているかを検証するもの

スパイ

  • 基本的にテストはメソッドへの入力に対して出力を検証する
  • 従ってvoid型のメソッドの検証はやりにくい
  • そこでロガーに書き込まれた内容を検証に使うスパイという手法がある
  • 基本的にはロガーのロギング機構にStringBufferへのappendの処理を追加して,検証時にtoStringして文字列比較するという単純なもの

Mockitoでスタブ・モックを作る

  • mockitoが適当に使える状況にしておく
  • Mock.mock(モックを作りたい対象のクラス)でモックが作れる
  • `where(モックのインスタンス.メソッド()).thenReturn(期待する返り値)Pで振る舞いを持たせられる
  • その他,コードを見ればきっと分かる!
  • 基本的にmockitoの使い方自体は簡単だけれど,そもそもスタブ・モックとは何かを理解できていないところがmockitoを使う上での最大の壁になると感じた
  • 現に本を読んで自分はちゃんとスタブ・モックがなにかを理解できていなかったので反省した