2013-02-08 4 views
7

Мне нужно уметь вводить код выхода для текущей текущей нити. Я боролся с этим на некоторое время, и я, наконец, пришел с решением здесь некоторый код похож на то, что я делаю:Обратный вызов обратного потока

public static void injectThreadExitCallback(final Runnable callback) { 
    final curr = Thread.currentThread(); 
    new Thread() { 
     @Override 
     public void run() { 
      try { 
       curr.join(); 
       callback.run(); 
      } catch (InterruptedException ex) { 
       ... logging ... 
      } 
     } 
    }.start(); 
} 

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

или это прекрасно, если это так полезно. Я мог видеть простую библиотеку, которая может динамически добавлять код выхода в существующие потоки.

+1

Выглядит хорошо; просто помните, что обратный вызов будет работать в отдельном потоке. –

+1

Перемещение обратного вызова к блоку 'finally' означает, что он будет запущен, если' join' выдает исключение, которое произойдет * до того, как завершит целевой поток. Кроме того, объединение никогда не будет генерировать исключение, если какой-либо внешний агент не начнет прерывать все потоки. –

+0

Если анонимный поток, созданный внутри этого метода, прерван, очень сомнительно, следует ли вызывать обратный вызов. Точка прерывания потока - это остановить то, что она делает. Поскольку единственное, что делает этот поток, это ожидание вызова обратного вызова, единственной причиной его прерывания было бы предотвращение запуска обратного вызова. –

ответ

3

Лучше сделать

new Thread() { 
    @Override 
    public void run() { 
     try 
     { 
      // Thread logic here 
     } 
     finally 
     { 
      // Thread exit logic here 
     } 
    } 
}.start(); 
+1

хорошо пункт! таким образом, если поток, который я обманываю, умирает, я все еще делаю то, что мне нужно сделать. –

+0

Это не совсем инъекция, не так ли? Код потока необходимо изменить, чтобы включить логику выхода потока. (Или вы говорите о реструктуризации предложенной пользователем инъекции для инъекций? –

+0

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

0

Вы можете перемещать callback.run(); после catch блока или в final блоке, если вы хотите, чтобы убедиться, что она называется так или иначе

+0

Вообще говоря, единственная причина прерывания потока - заставить его перестать делать то, что он делает. В этом случае единственное, что он делает, это ожидание вызова обратного вызова. Таким образом, вы определенно не делаете _not_ хотите убедиться, что обратный вызов вызывается, когда поток прерывается! –

+0

Это правда, но это зависит от погоды прикладной логики, которую вы хотите обеспечить, чтобы вызываемый вызов был вызван или нет. Так, например, если 'callback' выполняет некоторую задачу очистки, у вас будет законная причина, чтобы убедиться, что он вызывается, даже если поток прерывается. – iTech

2

Вы не можете, возможно, вводить код в если поток не активно взаимодействует, как, например, Thread Dispatch Thread в AWT, который у корня имеет цикл, который выводит Runnables из очереди и выполняет их.

Ваш дизайн может вводить данные в код, который ранее был однопоточным и, следовательно, не имел проблем с параллелизмом.

И, наконец, дизайн тратит драгоценный системный ресурс (нить), чтобы ничего не делать, кроме как ждать окончания другого потока.

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

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