如何限制方法调用以允许线程完成

时间:2013-09-23 19:19:44

标签: java multithreading threadpool

我目前有以下设置。在运行一段时间之后,我得到了内存异常;我怀疑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);
   }
}

修改

我的意思是表明我将循环索引传递给runnables。

3 个答案:

答案 0 :(得分:1)

你有10个线程,所以添加10个作业,你永远不会为了安排它们而耗尽内存。

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);
   }
}

答案 1 :(得分: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);
           }
    }
});

答案 2 :(得分: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。节省了大量物体,处理速度也很快。