2017-01-03 3 views
5

У меня есть управляемый объект A, который обменивается сердечными биениями с сервером при создании экземпляра. Я отправляю n таких объектов в службу-исполнитель с фиксированным размером пула потоков n. Когда метод запуска встретит исключение, он вернется. Для данного случая все мои потоки встречаются с исключением и возвратом, но созданный объект остается живым и продолжает обмениваться сигналами сердечного ритма. Как пометить такие объекты для сбора мусора, чтобы они прекратили обмен сигналами сердечного ритма?Когда запущен объект мусора, собранный в ExecutorService?

class A implements Runnable { 
    public void run(){ 
      try{ 
      \\throws error 
      } catch(Exception e){ 
      \\returns 
      } 
     } 

    public static void main(){ 
      ExecutorService executor = Executors.newFixedThreadPool(n) 
      for(i = 1 to n){ 
       A a = new A() 
       executor.submit(a) 
      } 
     } 
} 

Должен ли я поместить ожидающий вызов в конце моего основного номера и сделать возврат?

Редактировать:
постановка вопроса другой путь, один из способов прекратить ExecutorService после того, как все потоки возвращают будет вызывать отключение() после того как цикл и вызвать awaitTermination с Integer.MAX длинных секунд, что примерно 70 лет (это временное ограничение, которое я неохотно налагаю). Есть ли другая альтернатива?

+0

Я думаю, вы должны разместить код, который вы использовали для обмена биением сердца сигналы. – AmjadD

+0

Сердечный звонок не является явным, он создается через библиотеку. – ankshah

+2

Если вы все еще видите сердечные сокращения после завершения метода 'run()', у вас все еще есть «Runnable», который не вышел, даже если вы считаете, что у всех их есть *. Я предлагаю регистрировать идентификатор потока как самый первый шаг в 'run()', а также непосредственно перед каждым оператором return. Используйте 'Thread.currentThread(). GetId()'. – kdgregory

ответ

1

один способ прекратить ExecutorService после того, как все потоки возвращают будет вызывать отключение() после того как цикл и вызвать awaitTermination с Integer.MAX долгих секунд, который составляет примерно 70 лет

как Док говорит, что метод awaitTermination будет блокировать Util:

  1. все задачи завершили выполнение после запроса завершения работы
  2. или тайм-аут происходит,
  3. или текущий поток прерывается, в зависимости от того происходит первый


Так это будет игра закончена, как только один из трех случае повернуть вверх, а не придется ждать 70 лет.

+0

Моя проблема не в том, чтобы ждать 70 лет, а скорее мой код отключается после таймаута 70 лет :) – ankshah

+0

@ ankshah ваш код будет отключен после min (все задачи завершены, 70-летний тайм-аут, текущий поток прерывается) –

+1

Ты пропустил это снова. Я хочу, чтобы моя задача выполнялась _beyond_ 70 лет. Это потребитель сообщения, я хочу позволить ему потреблять более 70 лет. Очень оптимистично, я знаю. – ankshah

0

вызов shutdown() в пуле означает, что пул больше не будет принимать новую задачу для выполнения, но текущие будут работать без перерыва.

вызов awaitTermination (timeout) удерживает вызывающий поток до завершения пула, но если время ожидания достигнуто, то текущий поток выдает execption, но это не повлияет на задачи в пуле.

Если ваш runnable генерирует неиспользуемое исключение при запуске пула потоков, то эта runnable больше не находится в состоянии запуска - пул потоков обычно не ссылается на такой объект.

Если вы используете FixedThreadPool, то этот пул будет создавать столько потоков, сколько пожелаете, и не остановит их, пока вы не вызовете shutdown() в этом пуле.

Если у вас нет ссылки на выполняемый объект, который выбрасывает исключение, он ведет себя как обычный неопубликованный объект для сбора мусора.

если вы вызываете shutdown(), а затем ожидаетеTermination() в пуле потоков, и ваша программа не останавливается в любом случае, это означает, что не все экземпляры вашего runnable вызывают исключение, а некоторые все еще работают, блокируя пул от полного выключения.

В java вы не можете убить или прекратить выполнение потока точно так же (вы можете убить только целую JVM, используя, например, System.exit(0), но не только выбранный поток), если вам нужна такая функциональность, вам необходимо запрограммировать тело runnable таким образом, который позволяет вам как-то обмениваться с ним, т.е. используя некоторую переменную «volatile boolean», и что она ответит на изменение значения этой переменной - это означает, что вам нужно добавить «если проверки» для значения этой переменной в теле метода run(), который вернется когда это необходимо.

0

Задачи сами могут собираться для сбора мусора, как только их исполнение завершено. Если и когда они фактически собраны, это зависит от сборщика мусора.

Пример кода:

public class Main implements Runnable { 
    @Override 
    protected void finalize() throws Throwable { 
     super.finalize(); 
     System.out.println("finalize"); 
    } 

    @Override 
    public void run() { 
     try { 
      throw new Exception("Error"); 
     } catch (Exception e) { 
      //returns 
     } 
    } 

    public static void main(String args[]) { 
     int n = 8; 
     ExecutorService executor = Executors.newFixedThreadPool(n); 
     for (int i = 0 ; i < n; ++i) { 
      Main a = new Main(); 
      executor.submit(a); 
     } 
     System.gc(); 
     System.out.println("end"); 
    } 
} 

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

  • Нет связанных вопросов^_^