2012年7月24日火曜日

マルチスレッドの勉強本

今、これ読んでます。



すごいいいです。初心者には想像もつかない、コンパイラの最適化の動作やメモリの可視性についてなどが書いてあります。
私もまだ読み始めですが、とても勉強になります。

PropertiesファイルのKeySetで拡張for文

拡張for文を使って、Propertiesファイルからloadしたデータをまわしたいってことありませんか?

そうです。以下のメソッドでそれができます。
Properties props = new Properties();
Set<String> propNames = props.stringPropertyNames();

これでpropNamesにPropertiesファイルのKeyセットが入ります。
これを使って、以下のように拡張for文を書きましょう。

for(String key : propNames){ ... }

Mapになんでもかんでも詰め込まない

色々な型の、だけどすべてある事をするために必要なデータである、というだけでMapにバラバラのデータ型のデータを詰め込まない。
何のためにGenericsがあるの?って事になる。

集合としてみれるデータであれば、まだ入れる価値はあるかもしれないが、それでも型が異なる物は入れない方がよいし、中に何が入っているのかわかりにくくなる。

Mapを使うには理由をつけて使用すべき。
例えば、同じ種類の違う値、Keyを持つデータ群がある場合、Keyに意味を持たせ、例えば、Keyを文字列で連結して生成したり、などをして同じ種類のデータを取得するようにすれば、それはMapを使う意味があるだろう。

PipedInputStreamとPipedOutputStream

XSLT変換するとき、Transformerクラスってのを使います。
このクラスが持つtransformメソッドは、引数にStreamのInputとOutputを入力するようになっています。
でも、OutputStreamに何かを書き出してから、それをSourceとしてtransformしたい場合、Sourceの型はInputStreamになっているので、一旦ファイルに落として再読み込みしなければならない。。。

と思っていたのですが、PipedOutputStreamを使って、PipedInputStreamにconnectしてあげれば、OutputStreamをInputStreamに変換(?)、という事が可能です。


で、PipedOutputStreamをBufferedOutputStreamでWrapしてあげて、これに沢山のデータを突っ込んでいると、あるタイミングでflushが走ります。そうすると、PipedInputStreamが確保しているBuffer領域にデータが流し込まれます。
確保するBuffer領域は、デフォルトで1024bytesです。

また、このPipedInput/OutputStreamは、マルチスレッドで使用しないと、デッドロックが発生する可能性があります。

また、このPipedInput/OutputStreamを使用する時に注意すべき事があるのですが、OutputStream側が書き出しをしているのに、InputStream側がcloseしてしまうと、Exceptionを(確か)吐きます。
なので、closeするタイミングも気にしながら実装すると、バグを埋め込まないで実装できると思います。