2013-09-23 56 views
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); 
    } 
} 

編輯

我的意思是證明我的指數想過去爲循環的可運行。

+0

它的內存不足,因爲它創建了數以百萬計的'Runnable'對象並將它們存儲在執行程序隊列中的速度比它們可以執行的快。解決這個問題的唯一方法是以某種方式減慢for循環。例如,您可以讓'myMethod'記錄尚未執行的runnable數量,並且如果它高於某個數字,則會阻止直到它低於該數字。 – SamYonnou

+0

節流高度依賴於'方法體'。你可能不需要那些數十億的runnables。取決於'方法體'你可能只需要改變邏輯來支持節流。 – Claudiu

+0

@csoroiu添加了關於方法主體的信息。我想最主要的是我使用了體內for循環的索引。 – alh

回答

1

你有10個線程,所以添加10個作業,你永遠不會用盡內存試圖安排他們。

例如

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

我得到了FO內存異常運行了一小會兒後,我懷疑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); 
      } 
    } 
}); 
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的增量在每個工人彼得建議。節省很多物體和處理速度很高。

相關問題