0

我目前有以下设置。运行一段时间后,我正在退出内存异常;我怀疑 main 中的 for 循环导致过多的备份方法调用。如果我不想增加线程池大小,限制调用的最佳方法是什么?

public class ManagedThreads {
   private final static ExecutorService ex = Executors.newFixedThreadPool(10);

   public static void myMethod(final int i) {
      ex.execute(new Runnable() {
         public void run() {
             // method body  using i
         }
      });
   }

   public static void main(String[] args) {
      for (int i = 0; i < 1000000000; ++i)
         myMethod(i);
   }
}

编辑

我的意思是表明我正在将循环的索引传递给可运行对象。

4

3 回答 3

1

You have ten threads so add ten jobs and you will never run out of memory trying to schedule them.

e.g.

public class ManagedThreads {
   private final static ExecutorService ex = Executors.newFixedThreadPool(10);

   public static void myMethod(final int i) {
      ex.execute(new Runnable() {
         public void run() {
             // do every tenth task.
             for(int j = i; j < 1000000000; j += 10) {
                 // method body
             }
         }
      });
   }

   public static void main(String[] args) {
      for (int i = 0; i < 10; ++i)
         myMethod(i);
   }
}
于 2013-09-23T19:35:12.240 回答
1

运行一段时间后,我正在退出内存异常;我怀疑 main 中的 for 循环导致过多的备份方法调用。如果我不想增加线程池大小,限制调用的最佳方法是什么?

这是一个常见问题解答。在这里查看我的答案:Process Large File for HTTP Calls in Java

您需要定义自己的有界作业队列,然后定义一个RejectedExecutionHandler. 当尝试将超过 100 个作业添加到作业队列时,以下代码将阻塞。

BlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(100);
ThreadPoolExecutor threadPool =
     new ThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS, queue);
// we need our RejectedExecutionHandler to block if the queue is full
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandler() {
       @Override
       public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
           try {
                // this will block the producer until there's room in the queue
                executor.getQueue().put(r);
           } catch (InterruptedException e) {
                throw new RejectedExecutionException(
                   "Unexpected InterruptedException", e);
           }
    }
});
于 2013-09-23T19:39:32.283 回答
0

我会同意这个(它将允许每个工人在 CPU 时钟方面执行相同数量的工作)

    private final static ExecutorService ex = Executors.newFixedThreadPool(10);

    final static AtomicInteger counter = new AtomicInteger(0);
    public static void myMethod(final int i) {
       ex.execute(new Runnable() {
          public void run() {
              while (counter.getAndIncrement() < 1000000000) {
                  //method body
              }
          }
       });
    }

    public static void main(String[] args) {
       for (int i = 0; i < 10; ++i)
          myMethod(i);
    }
 }

或者按照彼得的建议在每个工人中增加 10 次。节省大量对象,处理速度高。

于 2013-09-23T20:03:29.587 回答