我正在执行数百万次迭代,我希望将其并行化。因此决定将任务[每次迭代]添加到线程池。
现在,如果我将所有迭代添加到线程池,它可能会抛出OutOfMemoryError
。我想优雅地处理它,所以有没有办法知道线程池中工作线程的可用性?
一旦可用,请将Runnable
添加到工作线程。
for(int i=0; i<10000000000; i++) {
executor.submit(new Task(i));
}
每项任务仅需1秒即可完成。
答案 0 :(得分:0)
为什么不设置可以并发运行的任务数量的限制。像:
HashSet<Future> futures = new HashSet<>();
int concurrentTasks = 1000;
for (int ii=0; ii<100000000; ii++) {
while(concurrentTasks-- > 0 && ii<100000000) {
concurrentTasks.add(executor.submit(new Task(ii)));
}
Iterator<Future> it = concurrentTasks.iterator();
while(it.hasNext()) {
Future task = it.next();
if (task.isDone()) {
concurrentTasks++;
it.remove();
}
}
}
答案 1 :(得分:0)
你想要使用这样的东西:
ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(MAX_PENDING_TASKS);
Executor executor = new ThreadPoolExecutor(MIN_THREADS, MAX_THREADS, IDLE_TIMEOUT, TimeUnit.SECONDS, queue, new ThreadPoolExecutor.CallerRunsPolicy());
for(int i=0; i<10000000000; i++) {
executor.submit(new Task(i));
}
基本上,您使用最小/最大线程和阵列支持队列创建线程池。当您达到待处理任务的限制时,&#34;调用者运行策略&#34;启动并且您的主线程最终运行下一个任务(为您的其他任务提供时间来完成并打开队列中的插槽)。
既然你已经声明你的任务很短暂,这似乎是一种最佳策略。
MAX_PENDING_TASKS
和MIN_THREADS
的值可以帮助您找出工作负载的最佳值,但MAX_PENDING_TASKS
应该至少两次MIN_THREADS
并且可能更像是10到100次。
答案 2 :(得分:-1)
您应该使用java.lang.Runtime
最大的内存问题可能是你的对象创建,而不是将它们添加到你的执行者,所以你应该在那里调用Runtime.getRuntime().freeMemory()
。