1. kazurof

    Posted

    kazurof
Changes in title
+ズンドコキヨシをJavaで
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,93 @@
+流行りのズンドコキヨシをJavaで書いてみた。
+
+# Streamで書いてみた
+
+``` Zundoko.java
+import java.util.stream.Stream;
+
+public class Zundoko {
+ public static void main(String args[]) {
+ StringBuilder sb = new StringBuilder();
+ Stream<String> stream = Stream.generate(() -> Math.random() > 0.5 ? "ズン" : "ドコ");
+ try {
+ stream.peek(s -> {
+ System.out.print(s);
+ sb.append(s);
+ if (sb.toString().endsWith("ズンズンズンズンドコ")) {
+ throw new RuntimeException();
+ }
+ }).forEach(s -> {
+ });
+ } catch (RuntimeException r) {
+ System.out.print("キ・ヨ・シ!");
+ }
+ }
+}
+```
+
+むりやりStreamで書いてみたが、終了の判定が例外処理で美しくない。それに終端処理したいがためだけに空の`forEach`をしてるし。[Eclipse Collections](https://www.eclipse.org/collections/ja/) を使えばRuby並に簡潔に行けるかなと思ってちょっと調べたが、そうでもないようだ。(私が知らないだけかもですが)
+
+# マルチスレッドで書いてみた
+
+``` ZundokoThread.java
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+public class ZundokoThread {
+ public static void main(String args[]) {
+ ExecutorService zunSer = Executors.newFixedThreadPool(1);
+ ExecutorService dokoSer = Executors.newFixedThreadPool(1);
+ ZundokoPool pool = new ZundokoPool(zunSer, dokoSer);
+
+ zunSer.submit(new PutTask("ズン", pool));
+ dokoSer.submit(new PutTask("ドコ", pool));
+ }
+}
+
+class PutTask implements Runnable {
+ String text;
+ ZundokoPool pool;
+
+ public PutTask(String text, ZundokoPool pool) {
+ this.text = text;
+ this.pool = pool;
+ }
+
+ @Override
+ public void run() {
+ while (true) {
+ try {
+ Thread.sleep((long) Math.random() * 100);
+ } catch (InterruptedException e) {
+ break;
+ }
+ pool.put(text);
+ }
+ }
+}
+
+class ZundokoPool {
+ StringBuilder sb = new StringBuilder();
+ ExecutorService zunSer;
+ ExecutorService dokoSer;
+
+ public ZundokoPool(ExecutorService zunSer, ExecutorService dokoSer) {
+ this.zunSer = zunSer;
+ this.dokoSer = dokoSer;
+ }
+
+ synchronized void put(String str) {
+ sb.append(str);
+ if (sb.toString().endsWith("ズンズンズンズンドコ")) {
+ System.out.println(sb + "キ・ヨ・シ!");
+ zunSer.shutdownNow();
+ dokoSer.shutdownNow();
+ }
+ }
+}
+```
+
+本当は、`Math.random()` を使わないで書くという一発芸を狙ってスレッドで書いてみたが、各スレッドの動作頻度をバラけさせるために結局使ってしまった。重要ポイントは、`InterruptedException`をキャッチしたら `break`するところだと思う。これをやらないと、キ・ヨ・シ!を出力した後もスレッドの処理が終わらない。また、これをやってもキ・ヨ・シ!出力後に`ZundokoPool#put()`が呼ばれる場合がある。ロックの管理をもっと丁寧に細かくやれば回避できるかな?
+
+もっと別の書き方ないかなあ。もっと面白い書き方ないかなあ。セミコロンレスJavaもコードゴルフ決して悪くないが新鮮味に欠ける。(実際に書いたほうが絶対的に偉いんだけど。)
+