109

Javaの複数のスレッドに関する数学的問題を解決したいと思います。私の数学の問題は、いくつかのスレッドで解決したい作業単位に分けることができます。

一定量のスレッドを処理したくはありませんが、代わりにCPUコアの数と一致するスレッドの数を使用します。私の問題は、このための簡単なチュートリアルがインターネットで見つからなかったことです。私が見つけたのは、固定スレッドの例だけです。

これはどのように行うことができますか?例を挙げていただけますか?

4

6 に答える 6

120

静的ランタイム メソッドavailableProcessorsを使用して、Java 仮想マシンで使用可能なプロセスの数を決定できます。使用可能なプロセッサの数を決定したら、その数のスレッドを作成し、それに応じて作業を分割します。

更新:さらに明確にするために、スレッドはJavaの単なるオブジェクトであるため、他のオブジェクトを作成するのと同じように作成できます。したがって、上記のメソッドを呼び出して、2 つのプロセッサが返されることがわかったとします。素晴らしい。これで、新しいスレッドを生成し、そのスレッドの作業を分割し、スレッドを起動するループを作成できます。私が何を意味するかを示すための擬似コードを次に示します。

int processors = Runtime.getRuntime().availableProcessors();
for(int i=0; i < processors; i++) {
  Thread yourThread = new AThreadYouCreated();
  // You may need to pass in parameters depending on what work you are doing and how you setup your thread.
  yourThread.start();
}

独自のスレッドを作成する方法の詳細については、このチュートリアルに進んでください。また、スレッドの作成についてスレッド プーリングを確認することもできます。

于 2009-12-30T15:51:50.020 に答える
65

おそらく、これについても java.util.concurrent フレームワークを見たいと思うでしょう。何かのようなもの:

ExecutorService e = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
// Do work using something like either
e.execute(new Runnable() {
        public void run() {
            // do one task
        }
    });

また

    Future<String> future = pool.submit(new Callable<String>() {
        public String call() throws Exception {
            return null;
        }
    });
    future.get();  // Will block till result available

これは、独自のスレッドプールなどに対処するよりもはるかに優れています.

于 2009-12-30T16:03:53.680 に答える
11

オプション1:

newWorkStealingPoolからExecutors

public static ExecutorService newWorkStealingPool()

使用可能なすべてのプロセッサをターゲット並列処理レベルとして使用して、ワークスティーリング スレッド プールを作成します。

この API を使用すると、コア数を に渡す必要がなくなりますExecutorService

grepcodeからのこの API の実装

/**
     * Creates a work-stealing thread pool using all
     * {@link Runtime#availableProcessors available processors}
     * as its target parallelism level.
     * @return the newly created thread pool
     * @see #newWorkStealingPool(int)
     * @since 1.8
     */
    public static ExecutorService newWorkStealingPool() {
        return new ForkJoinPool
            (Runtime.getRuntime().availableProcessors(),
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
    }

オプション 2:

Executorsまたはからother newXXX constructorsnewFixedThreadPool API 。ExecutorService

public static ExecutorService newFixedThreadPool(int nThreads)

nThreads を次のように置き換えます Runtime.getRuntime().availableProcessors()

オプション 3:

ThreadPoolExecutor

public ThreadPoolExecutor(int corePoolSize,
                      int maximumPoolSize,
                      long keepAliveTime,
                      TimeUnit unit,
                      BlockingQueue<Runnable> workQueue)

Runtime.getRuntime().availableProcessors()にパラメータとして渡しますmaximumPoolSize

于 2016-04-19T15:48:44.470 に答える
8

Doug Lea (concurrent パッケージの作成者) には、関連する可能性のあるこの論文があります: http://gee.cs.oswego.edu/dl/papers/fj.pdf

Fork Join フレームワークが Java SE 7 に追加されました。以下にいくつかのリファレンスを示します。

http://www.ibm.com/developerworks/java/library/j-jtp11137/index.html Brian Goetz による記事

http://www.oracle.com/technetwork/articles/java/fork-join-422606.html

于 2009-12-30T19:22:38.113 に答える
4

標準的な方法は、Runtime.getRuntime().availableProcessors() メソッドです。ほとんどの標準的な CPU では、最適なスレッド数 (実際の CPU コア数ではありません) がここに返されます。したがって、これはあなたが探しているものです。

例:

ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

次のようにエグゼキュータ サービスをシャットダウンすることを忘れないでください (そうしないと、プログラムが終了しません)。

service.shutdown();

ここでは、未来ベースの MT コードをセットアップする方法の簡単な概要を示します (説明のために、トピック外です)。

CompletionService<YourCallableImplementor> completionService = 
    new ExecutorCompletionService<YourCallableImplementor>(service);
    ArrayList<Future<YourCallableImplementor>> futures = new ArrayList<Future<YourCallableImplementor>>();
    for (String computeMe : elementsToCompute) {
        futures.add(completionService.submit(new YourCallableImplementor(computeMe)));
    }

次に、予想される結果の数を追跡し、次のように取得する必要があります。

try {
  int received = 0;
  while (received < elementsToCompute.size()) {
     Future<YourCallableImplementor> resultFuture = completionService.take(); 
     YourCallableImplementor result = resultFuture.get();
     received++; 
  }
} finally {
  service.shutdown();
}
于 2015-11-02T21:23:58.123 に答える
3

Runtime クラスには、availableProcessors() というメソッドがあります。これを使用して、使用している CPU の数を把握できます。プログラムは CPU バウンドであるため、使用可能な CPU ごとに (多くても) 1 つのスレッドが必要になるでしょう。

于 2009-12-30T15:51:21.457 に答える