2012-04-08 3 views
2

У меня есть вопрос Java mulithreading. У меня есть следующий класс работника:Проблемы с кучей Java ExecutorService

public class ThreadWorker implements Runnable { 

    //some code in here 

    public void run(){ 
     // invokes some recursion method in the ThreadWorker itself, 
     // which will stop eventually 
    { 
} 

Для работы с потоками Я использую ExecutorService:

public static int THREAD_NUMBER = 4; 
public static ExecutorServide es = Executors.newFixedThreadPool(THREAD_NUMBER); 

Добавления экземпляров класса ThreadWroker происходит здесь:

public void recursiveMethod(Arraylist<Integers> elements, MyClass data){ 
    if (elements.size() == 0 && data.qualifies()){ 
     ThreadWorker tw = new ThreadWorker(data); 
     es.execute(tw); 
     return; 
    } 



    for (int i=0; i< elements.size(); i++){ 
      // some code to prevent my problem 
      MyClass data1 = new MyClass(data); 
      MyClass data2 = new MyClass(data); 
      ArrayList<Integer> newElements = (ArrayList<Integer>)elements.clone(); 
      data1.update(elements.get(i)); 
      data2.update(-1 * elements.get(i)); 
      newElements.remove(i); 
      recursiveMethod(newElements, data1); 
      recursiveMethod(newElements, data2);  
    {  
} 

Проблема заключается в том что глубина рекурсивного дерева довольно велика, так как это ширина, поэтому в добавлено много ThreadWorkers, поэтому через некоторое время на би г ввести получить

Exception in thread "pool-1-thread-2" java.lang.OutOfMemoryError: Java heap space 

, которое вызывается, как я думаю, что из-за Ginormous числа ThreadWorkers я добавляю к ExecutorSirvice быть выполнена, так что бежит из памяти. Каждый ThreadWorker занимает около 40 МБ ОЗУ для всех, в чем он нуждается.

Есть ли способ, чтобы узнать, сколько потоков (экземпляров классов, реализующих runnable interface) было добавлено в ExecutorService? Так что я могу добавить его в показанный выше код (интермедиат «// некоторый код, чтобы предотвратить мою проблему»), так как

while ("number of threads in the ExecutorService" > 10){ 
    Thread.sleep(10000); 
} 

, так что я не буду вдаваться в глубокие или широкие с моей рекурсии и предотвратить те ситуации исключения.

С уважением, Сергей Аганезов младший.

ответ

6

Как насчет создания ThreadPoolExecutor с поддержкой BlockingQueue с использованием ThreadPoolExecutor.CallerRunsPolicy.

Таким образом, при отсутствии рабочих потоков для запуска задачи основной поток (который добавляет новые задания) запускает сама задача, что предотвращает добавление большего количества заданий.

Более подробную информацию о вариантах конструктора для ThreadPoolExecutor можно найти на странице Javadoc.

+0

Создать 'TreadPoolExecutor эс = новый ThreadPoolExecutor (4, 4, 10000, TimUnit.MILLISECONDS, новый ArrayBlockingQueue (10));' , а затем установить rejectedHandler к нему 'es.setRejectedExecutionHandler (новый ThreadPoolExecutor .CallerRunsPolicy()); '. После этого, если я это правильно понимаю, он справится с моей проблемой, так как количество запущенных потоков достигает 4, а количество потоков в очереди достигает 10, следующая добавленная задача будет отклонена и будет выполняться основной поток, останавливая все остальные деятельность в нем. –

+0

Да, это так. – ulmangt

1

Я думаю, что ваш случай подходит для рамки «fork-join» Java JDK. (Google для этого ключевого слова.)

Fork-Join помогает вам сократить количество заданий в очереди, отложив «раскол» как можно дальше.

Вы должны переформулировать свой код в этой философии.

Смежные вопросы