仅当一个或多个工作线程可用时才创建和添加Runnable ..?

时间:2014-08-25 19:37:38

标签: java multithreading threadpool executorservice executor

我正在执行数百万次迭代,我希望将其并行化。因此决定将任务[每次迭代]添加到线程池。

现在,如果我将所有迭代添加到线程池,它可能会抛出OutOfMemoryError。我想优雅地处理它,所以有没有办法知道线程池中工作线程的可用性?

一旦可用,请将Runnable添加到工作线程。

for(int i=0; i<10000000000; i++) {
     executor.submit(new Task(i));
}

每项任务仅需1秒即可完成。

3 个答案:

答案 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_TASKSMIN_THREADS的值可以帮助您找出工作负载的最佳值,但MAX_PENDING_TASKS应该至少两次MIN_THREADS并且可能更像是10到100次。

答案 2 :(得分:-1)

您应该使用java.lang.Runtime

最大的内存问题可能是你的对象创建,而不是将它们添加到你的执行者,所以你应该在那里调用Runtime.getRuntime().freeMemory()