LoginSignup
4
4

More than 5 years have passed since last update.

マルチプロセス(マルチスレッド)でのFizzBuzzって?

Posted at

マルチプロセス(マルチスレッド)のプログラムってとても難しいですね。
特にJavaScript(TypeScript)の場合はことさら難しいと思いました。

そこで、練習のためにマルチプロセスでのFizzBuzzを以下の仕様を満たすように作ってみました。

  • FizzBuzz値を算出する複数のワーカープロセス(ワーカースレッド)を使う
  • ワーカープロセス(ワーカースレッド)からメインプロセス(メインスレッド)に算出した結果を送信する
  • メインプロセス(メインスレッド)では(逐次出力ではなく)結果がすべて揃った後に、結果をまとめて出力する
  • 出力する形式(文字列)の細かいところは問わないこととする

以下は、Node.jsのclusterを使ったマルチプロセス版(TypeScript)です。
RxJSだったらどうなるのか少し気になりますね。
もっと簡単にできるのでしょうか?

fizzbuzz.ts
import * as cluster from "cluster";
import * as events from "events";
events.EventEmitter.defaultMaxListeners = 30;

function* range(begin: number, end: number) {
    for (let i = begin; i <= end; i++) {
        yield i;
    }
}

function fizzbuzz(i: number) {
    return i % 15 === 0 ? "FizzBuzz"
        : i % 5 === 0 ? "Buzz"
            : i % 3 === 0 ? "Fizz"
                : i.toString();
}

async function main() {
    if (cluster.isMaster) {
        const promises = Array.from(range(1, 30)).map((i) => {
            return new Promise<[number, string]>((resolve) => {
                cluster.on("message", (worker, [index, result]: [number, string]) => {
                    if (i === index) {
                        resolve([i, result]);
                    }
                });
            });
        });
        for (const i of range(1, 30)) {
            const worker = cluster.fork();
            worker.on("online", () => {
                worker.send(i);
            });
        }
        const map = new Map(await Promise.all(promises));
        console.log(map);

        Object.values(cluster.workers).forEach((w) => w!.kill());
    } else {
        process.on("message", (i) => {
            process.send!([i, fizzbuzz(i)]);
        });
    }
}

if (require.main === module) {
    main();
}

ポイントはPromiseを作ってからfork/sendして、そのあとawaitで待つことです。
結果は以下のようになります。

> Executing task: npm-run ts-node src/fizzbuzz.ts <

Map {
  1 => '1',
  2 => '2',
  3 => 'Fizz',
  4 => '4',
  5 => 'Buzz',
  6 => 'Fizz',
  7 => '7',
  8 => '8',
  9 => 'Fizz',
  10 => 'Buzz',
  11 => '11',
  12 => 'Fizz',
  13 => '13',
  14 => '14',
  15 => 'FizzBuzz',
  16 => '16',
  17 => '17',
  18 => 'Fizz',
  19 => '19',
  20 => 'Buzz',
  21 => 'Fizz',
  22 => '22',
  23 => '23',
  24 => 'Fizz',
  25 => 'Buzz',
  26 => '26',
  27 => 'Fizz',
  28 => '28',
  29 => '29',
  30 => 'FizzBuzz' }
4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4