FixThreadPool 和 ExecutorCompletionService 出现 OutOfMemory 错误

发布于 2024-12-12 09:19:06 字数 2119 浏览 0 评论 0原文

我正在开发应用程序,应该从数据库获取用户列表并从目录(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);
}

}

I working on app what should get list of users from db and update thie details from directory (ldap or AD). I what do this procedure on multicore machine so I created this app (code below). I'm using CompletionService and getting the results in Future object.

After some time, I'm getting out of memory error with 'unable to create new native thread' message. In task manager I see that app created enormous amount of threads but I asked create fixed thread pool with size equals amount of my processors.

What is wrong with my code?

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);
}
}

ERROR CheckGroupMembership:85 - java.lang.OutOfMemoryError: unable to create new native thread
java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: unable to create new native thread
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)
at java.util.concurrent.FutureTask.get(FutureTask.java:83

GetuserDLs task

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);
}

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

陌若浮生 2024-12-19 09:19:06

我很难相信您没有在 GetUsersDLTask 中创建线程(或者至少是服务对象)。如果您查看堆栈跟踪,就会发现异常是从 Future 的 get() 方法引发的。设置此异常的唯一方法是在执行器调用 Callabale.call() 后。在 call() 方法中发生的任何 throwable 都将在 Future 的内部 exception 字段中设置

例如:

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

否则,当您向线程提交请求时,就会发生此异常池,而不是当你从未来获得时。

I am having a hard time believing you are not creating a Thread in GetUsersDLTask (or at least it's service Object). If you look at your stacktrace, the Exception is being thrown from the Future's get() method. The only way this exception get's set is after the Executor invokes Callabale.call(). Any throwable that occurs in the call() method will be set in the Future's internal exception field

For example:

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

Otherwise, this exception would be occurring when you submit the ask to thread pool, not when you get from the future.

波浪屿的海角声 2024-12-19 09:19:06

Executors.newFixedThreadPool 将接受许多任务的提交,但只会执行您允许的线程数。因此,如果您有 2 个线程的固定池,但提交了 50 个任务,则其他 48 个任务将在执行器内部排队,并在执行线程完成任务时运行。似乎您需要限制代码中生成的线程数量。

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

Executors.newFixedThreadPool will accept the submission of many tasks, but will only execute the number of threads that you allow. So if you have a fixed pool of 2 threads, but you submit 50 tasks, the 48 other tasks are queued internally on the executor and are run as the executing threads finish tasks. Seems like you need to limit the number of threads you are spawning within your code.

Edit: check out http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool(int)

年少掌心 2024-12-19 09:19:06

您是否验证了固定池中创建的线程数。也许可用处理器的数量太大了。

Did you verify the number of threads created in the fixed pool. Maybe the # of available processors is coming out as too big.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文