web-dev-qa-db-ja.com

Javaマルチスレッドを使用してforループを並列化する

私はJava=に非常に慣れていないため、executorサービスまたはJavaの他のメソッドを使用してネストされたforループを並列化したいと思います。CPUが完全ではないように、いくつかの固定数のスレッドを作成したいと思います。スレッドによって取得されます。

    for(SellerNames sellerNames : sellerDataList) {
        for(String selleName : sellerNames) {
        //getSellerAddress(sellerName)
        //parallize this task
        }
    }

sellerDataListのサイズ= 1000、sellerNamesのサイズ= 5000。

ここで、10個のスレッドを作成し、タスクの等しいチャンクを各スレッドに均等に割り当てたいと思います。それは私がthellerDataListの場合、最初のスレッドは500の名前のアドレスを取得し、2番目のスレッドは次の500の名前のアドレスを取得する必要があります。
この仕事をするための最良の方法は何ですか?

9
Jhutan Debnath

並列実行するには、ストリームとエグゼキューターの2つの方法があります。

ストリームの使用

並列ストリームを使用して、残りをjvmに任せることができます。この場合、いつ何が起こるかをあまり制御できません。一方、コードは読みやすく、保守も簡単です。

    sellerDataList.stream().forEach(sellerNames -> {
        Stream<String> stream = StreamSupport.stream(sellerNames.spliterator(), true); // true means use parallel stream
        stream.forEach(sellerName -> {
            getSellerAddress(sellerName);
        });
    });

ExecutorServiceの使用

5つのスレッドが必要で、タスクが完了するまで待機できるようにしたいとします。次に、5つのスレッドを持つ固定スレッドプールを使用し、Future- sを使用して、完了するまで待つことができます。

    final ExecutorService executor = Executors.newFixedThreadPool(5); // it's just an arbitrary number
    final List<Future<?>> futures = new ArrayList<>();
    for (SellerNames sellerNames : sellerDataList) {
        for (final String sellerName : sellerNames) {
            Future<?> future = executor.submit(() -> {
                getSellerAddress(sellerName);
            });
            futures.add(future);
        }
    }
    try {
        for (Future<?> future : futures) {
            future.get(); // do anything you need, e.g. isDone(), ...
        }
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
13
Tamas Rev