FixThreadPool 和 ExecutorCompletionService 出现 OutOfMemory 错误
我正在开发应用程序,应该从数据库获取用户列表并从目录(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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我很难相信您没有在 GetUsersDLTask 中创建线程(或者至少是服务对象)。如果您查看堆栈跟踪,就会发现异常是从 Future 的 get() 方法引发的。设置此异常的唯一方法是在执行器调用 Callabale.call() 后。在
call()
方法中发生的任何 throwable 都将在 Future 的内部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'sget()
method. The only way this exception get's set is after the Executor invokesCallabale.call()
. Any throwable that occurs in thecall()
method will be set in the Future's internalexception
fieldFor example:
Otherwise, this exception would be occurring when you submit the ask to thread pool, not when you get from the future.
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)
您是否验证了固定池中创建的线程数。也许可用处理器的数量太大了。
Did you verify the number of threads created in the fixed pool. Maybe the # of available processors is coming out as too big.