4

私は、dbからユーザーのリストを取得し、ディレクトリ(ldapまたはAD)から詳細を更新する必要があるアプリに取り組んでいます。マルチコアマシンでこの手順を実行するため、このアプリを作成しました(以下のコード)。CompletionService を使用して、Future オブジェクトで結果を取得しています。

しばらくすると、「新しいネイティブ スレッドを作成できません」というメッセージでメモリ不足エラーが発生します。タスクマネージャーで、アプリが大量のスレッドを作成したことがわかりますが、サイズがプロセッサの量に等しい固定スレッドプールを作成するように依頼しました。

コードの何が問題になっていますか?

class CheckGroupMembership {
public static void main(String[] args) throws Exception {

    final ExecutorService executor = Executors.newFixedThreadPool(**Runtime.getRuntime().availableProcessors()**);

    CompletionService<LdapPerson> completionService =
        new ExecutorCompletionService(executor)<LdapPerson>(executor);

    final int limit = 2000;

    DocumentService service1 = new DocumentService();
    List<String> userNamesList = service1.getUsersListFromDB(limit);

    List<LdapPerson> ldapPersonList = new ArrayList() <LdapPerson> (userNamesList.size());
    LdapPerson person;

    for (String userName : userNamesList) {
        completionService.submit(new GetUsersDLTask(userName));
    }

    try {
        for (int i = 0, n = userNamesList.size(); i < n; i++) {
            Future<LdapPerson> f = completionService.take();
            person = f.get();
            ldapPersonList.add(person);
        }
    } catch (InterruptedException e) {

        System.out.println("InterruptedException error:" + e.getMessage());
    } catch (Exception e) {
        System.out.println(e.getMessage());
    }
    System.exit(0);
}
}

エラー CheckGroupMembership:85 - java.lang.OutOfMemoryError: 新しいネイティブ スレッドを作成できません java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: java.util.concurrent.FutureTask$Sync.innerGet で新しいネイティブ スレッドを作成できません( FutureTask.java:222) で java.util.concurrent.FutureTask.get(FutureTask.java:83)

GetuserDLs タスク

public class GetUsersDLTask implements Callable<LdapPerson> {
private String userName;

public GetUsersDLTask(String u) {
    this.userName = u;
}

@Override
public LdapPerson call() throws Exception {
    LdapService service = new LdapService();
    return service.getUsersDLs(userName);
}

}
4

3 に答える 3

3

あなたがスレッドを作成していないGetUsersDLTask(または少なくともサービスオブジェクトである)とは信じがたいです。スタック トレースを見ると、Future のget()メソッドから例外がスローされています。この例外が設定される唯一の方法は、Executor が を呼び出した後Callabale.call()です。メソッドで発生するスロー可能なものはcall()、Future の内部exceptionフィールドに設定されます

例えば:

Thread Pool: 
    Thread-1
      invoke call()
        call() 
          Create Thread
            throw OutOfMemoryError 
         propogate error to Thread pool
      set exception

そうしないと、この例外は、未来から取得したときではなく、スレッド プールに依頼を送信したときに発生します。

于 2011-10-27T17:36:07.770 に答える
0

固定プールに作成されたスレッドの数を確認しましたか。使用可能なプロセッサの数が多すぎると判明している可能性があります。

于 2011-10-27T17:25:05.187 に答える