簡體   English   中英

FixedThreadPool和ExecutorCompletionService的OutOfMemory錯誤

[英]OutOfMemory error with FixedThreadPool and ExecutorCompletionService

我在應用程序上工作,應該從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)at 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);
}

}

我很難相信你沒有在GetUsersDLTask (或至少它的服務對象)中創建一個Thread。 如果查看堆棧跟蹤,則會從Future的get()方法拋出異常。 設置此異常的唯一方法是在Executor調用Callabale.call() call()方法中出現的任何throwable都將在Future的內部exception字段中設置

例如:

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

否則,當您向線程池提交請求時,將發生此異常,而不是在您將來獲得此異常時。

Executors.newFixedThreadPool將接受許多任務的提交,但只會執行您允許的線程數。 因此,如果您有一個包含2個線程的固定池,但是您提交了50個任務,那么其他48個任務將在執行程序內部排隊,並在執行線程完成任務時運行。 您似乎需要限制在代碼中生成的線程數。

編輯:查看http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool(int

您是否驗證了固定池中創建的線程數。 也許可用的處理器數量太大了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM