我正在研究应该从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);
}
}
ERROR CheckGroupMembership:85 - java.lang.OutOfMemoryError:无法创建新的本机线程 java.util.concurrent.ExecutionException:java.lang.OutOfMemoryError:无法创建新的本机线程 at 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);
}
}
答案 0 :(得分:2)
我很难相信你没有在GetUsersDLTask
(或者至少是它的服务对象)中创建一个线程。如果查看堆栈跟踪,则会从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
否则,当您向线程池提交请求时,将发生此异常,而不是从将来获得此异常。
答案 1 :(得分:0)
Executors.newFixedThreadPool将接受许多任务的提交,但只会执行您允许的线程数。因此,如果您有一个包含2个线程的固定池,但是您提交了50个任务,那么其他48个任务将在执行程序内部排队,并在执行线程完成任务时运行。好像你需要限制你在代码中产生的线程数。
答案 2 :(得分:0)
您是否验证了固定池中创建的线程数。也许可用的处理器数量太大了。