Javaアプリケーションでスレッドを使用して、(ネットワーク呼び出しを使用して)データを並列に取得しています。スレッドプールを作成し、スレッドサイズを(最大10-15)とするメソッドを持っていて、それらをネットワーク呼び出しに使用しています。そのメソッドをループから数回呼び出しています。Javaでスレッドをあまりにも多く作成する
このアプリケーションを低速マシン(3GB RAM、Pentium-IV)で動作させると、すべて正常に動作しますが、iMac(32GB RAM、i7プロセッサ)上で実行すると、時々約2500とメモリエラーをスローします。
私は、JVMが完成したスレッドをすぐにプールに戻さないと思っています。つまり、完了したスレッドはすぐに新しいスレッドを作成します。
さらにiMacでも、もし私がThread.sleep(1000)を持っていれば、上記のforループですべてうまく動作します。しかし約900スレッドを作成します。
は、以下のコード、このアプリケーションからのサンプルである:私はiMacのループについては、以下の使用して上記の方法を呼び出す場合
public ArrayList<String> getValuesForKeyFromMaps(String key, ArrayList<Meta> locations) throws InterruptedException, ExecutionException{
int threadNum = locations.size(); // 10-15 at max
ExecutorService executor = Executors.newFixedThreadPool(threadNum);
List<FutureTask<ArrayList<String>>> taskList = new ArrayList<FutureTask<ArrayList<String>>>();
for(final Meta location : locations){
FutureTask<ArrayList<String>> futureTask_1 = new FutureTask<ArrayList<String>>(new Callable<ArrayList<String>>() {
public ArrayList<String> call() throws Exception {
// service call
return getValues(key, location);
}
});
taskList.add(futureTask_1);
executor.execute(futureTask_1);
}
ArrayList<String> values = new ArrayList<String>();
// Wait until all results are available and combine them at the same time
for (int j = 0; j < threadNum; j++) {
FutureTask<ArrayList<String>> futureTask = taskList.get(j);
values.addAll(futureTask.get());
}
executor.shutdown();
return values;
}
、そのは、約2500のスレッドを作成するので、メモリエラーをスロー。しかし、遅いマシンでうまく動作します。
for(String key : keySet){
getValuesForKeyFromMaps(key, metaMap.get(key));
}
そして、以下のコードでは、iMacでは約900スレッドで動作します。
for(String key : keySet){
getValuesForKeyFromMaps(key, metaMap.get(key));
Thread.sleep(200); //sleeping for 200ms
}
私は1000ミリ秒にループのために上記に睡眠時間を増やす場合は、その作成のみ30-50スレッドとアプリケーションが正常に動作しています。
アプリケーションで許可されている最大スレッドを制御するにはどうすればよいですか。私は作成時に最大10-15のスレッドを使用することを意図していますが、Javaではたくさんのスレッドが作成されています。
2500またはさらに900スレッドです。あなたはそれで何をしたいですか? –
これを参照してください:http://stackoverflow.com/questions/763579/how-many-threads-can-a-java-vm-support –
「900スレッドの作成」のようなものは表示されません。まず、いくつかのスレッドを 'locations.size()'に固定してエグゼキュータを作成します。次に、この場所のコレクションを繰り返し、場所ごとに1つのタスクを作成し、スレッドプールに追加します。この場所のサイズは、あなたが思ったよりもはるかに多いか、10-15(最大)のタスクしか作成していません。そして... ...ところで...このコードスニペットの外にスレッドプールを作成してください。 – Seelenvirtuose