Java8新機能 ラムダ式で並列処理
一昨日の記事で繰り返し処理をラムダ式で書きましたが、 ラムダ式のいいところは短くなるだけではなく、並列処理が出来るということらしいので朝一でやってみました。
まずは普通に
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5); SimpleDateFormat DF = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); long start = System.currentTimeMillis(); for (int x : list) { try { Thread.sleep(1000); } catch(Exception e){} System.out.println(DF.format(new Date()) + ":" + x); } long end = System.currentTimeMillis(); System.out.println((end - start) + "ms");
出力結果
2013/05/29 09:28:37:1
2013/05/29 09:28:38:2
2013/05/29 09:28:39:3
2013/05/29 09:28:40:4
2013/05/29 09:28:41:5
5001ms
1つ出力するたびに1秒停止しているので、当然ながら5秒程度かかります。
ラムダ式で
start = System.currentTimeMillis(); list.forEach(x->{ try { Thread.sleep(1000); } catch(Exception e){} System.out.println(DF.format(new Date()) + ":" + x); }); end = System.currentTimeMillis(); System.out.println((end - start) + "ms");
出力結果
2013/05/29 09:28:42:1
2013/05/29 09:28:43:2
2013/05/29 09:28:44:3
2013/05/29 09:28:45:4
2013/05/29 09:28:46:5
5015ms
あれ、やっぱり5秒。全然並列処理になってない orz
並列処理のラムダ式で
Javadocを見てみたら、ListクラスにparallelStreamというメソッドがあったので使ってみると
System.out.println("---"); start = System.currentTimeMillis(); list.parallelStream().forEach(x->{ try { Thread.sleep(1000); } catch(Exception e){} System.out.println(DF.format(new Date()) + ":" + x); }); end = System.currentTimeMillis(); System.out.println((end - start) + "ms");
出力結果
2013/05/29 09:28:52:5
2013/05/29 09:28:52:2
2013/05/29 09:28:52:1
2013/05/29 09:28:53:4
2013/05/29 09:28:53:3
2005ms
無事並列処理になりました。
ただ、最初3個が同時に出力された後に残り2個が出力されるので、同時に3つまでしか並列処理されていないようです。この数はCPU数になるっぽいですね。
ちなみにparallelStreamの部分は
list.stream().parallel().forEach(~
でもOKです。
気になったこと
ここで使ってるSimpleDateFormatってスレッドセーフじゃないんですよねw
他にもArrayListとかHashMapとかStringBuilderとか、かなり使用頻度高いクラスも同様なので、並列処理にする時は気をつけましょう。