Javaの複数のスレッドで数学的な問題を解決したいと思います。私の数学の問題は、複数のスレッドで解決したい作業単位に分割できます。
一定量のスレッドを処理するのではなく、CPUコアの量と一致する量のスレッドを使用する必要があります。私の問題は、インターネットで簡単なチュートリアルを見つけることができなかったことです。私が見つけたすべては、固定スレッドの例です。
これはどのように行うことができますか?例を提供できますか?
Javaの複数のスレッドで数学的な問題を解決したいと思います。私の数学の問題は、複数のスレッドで解決したい作業単位に分割できます。
一定量のスレッドを処理するのではなく、CPUコアの量と一致する量のスレッドを使用する必要があります。私の問題は、インターネットで簡単なチュートリアルを見つけることができなかったことです。私が見つけたすべては、固定スレッドの例です。
これはどのように行うことができますか?例を提供できますか?
回答:
静的なランタイムメソッド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();
}
独自のスレッドの作成の詳細については、このチュートリアルをご覧ください。また、スレッドの作成については、スレッドプールを確認することもできます。
おそらく、これについても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
これは、独自のスレッドプールなどに対処するよりもはるかに優れています。
オプション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:
newFixedThreadPoolのからのAPI Executors
やother newXXX constructors
、返品ExecutorService
public static ExecutorService newFixedThreadPool(int nThreads)
nThreadsを Runtime.getRuntime().availableProcessors()
オプション3:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue)
Runtime.getRuntime().availableProcessors()
パラメータとしてに渡しますmaximumPoolSize
。
Doug Lea(コンカレントパッケージの作者)は、この論文を関連性があるとしています。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
標準的な方法は、Runtime.getRuntime()。availableProcessors()メソッドです。ほとんどの標準CPUでは、最適なスレッド数(実際のCPUコア数ではない)がここに返されます。したがって、これはあなたが探しているものです。
例:
ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
次のようにexecutorサービスをシャットダウンすることを忘れないでください(そうしないと、プログラムは終了しません)。
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();
}
Runtimeクラスには、availableProcessors()というメソッドがあります。これを使用して、CPUの数を把握できます。プログラムはCPUバウンドであるため、使用可能なCPUごとに(最大で)1つのスレッドが必要になるでしょう。