2011-07-11 69 views
0

我正在嘗試編寫多線程程序的一部分,其中來自固定線程池的每個線程都嘗試從隊列中獲取對象,並且如果隊列爲空,線程將等待。爲什麼ExecutorService在線程被阻塞時保持執行狀態?

我遇到的問題是程序使用的內存不斷增加。

public class Ex3 { 

public static LinkedBlockingQueue<Integer> myLBQ = new LinkedBlockingQueue<Integer>(10); 

public static void main(String argc[]) throws Exception { 
    ExecutorService executor = Executors.newFixedThreadPool(3); 
    myLBQ.add(new Integer(1)); 
    for (;;) { 
     executor.execute(new MyHandler(myLBQ)); 
    } 
} 
} 

class MyHandler implements Runnable { 

LinkedBlockingQueue<Integer> myLBQ; 

MyHandler(LinkedBlockingQueue<Integer> myLBQ) { 
    this.myLBQ = myLBQ; 
} 

public void run() { 
    try { 
     myLBQ.take(); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 
} 

我不明白爲什麼當線程應該等待一個項目添加到隊列時,executor.execute會持續觸發。如何修改我的代碼以反映這一點?

回答

1

這可以儘快向執行者添加任務。

for (;;) { 
    executor.execute(new MyHandler(myLBQ)); 
} 

這將消耗約200 MB每秒。它與任務是否有任何關係沒有關係。

如果你不想這樣做,我建議你將循環移到runnable並只添加一個。這將導致它永遠等待任務。


一個更好的辦法是使用的ExecutorService的內置隊列中排隊的任務。

ExecutorService executor = Executors.newFixedThreadPool(3); 
final int taskId = 1; 
executor.submit(new Runnable() { 
    @Override 
    public void run() { 
     doSomething(taskId); 
    } 
}); 

executor.shutdown(); 

這是做同樣的事情,但更簡單恕我直言。

+0

謝謝,我沒有意識到,無論線程是否可用來執行它們,項目都會被添加到隊列中。 – Mat

+0

您可以更改它以拒絕任務,並且沒有等待線程,但這通常會導致「RejectedExecutionException」,這不是您想要的。 –

0

這是因爲您正在創建一個gazillion MyHandler實例並將它們插入到執行程序的內部隊列中。

無限循環是相當的意思。

相關問題