Редактировать
Я понял:
Порядок, в котором я инициализировал Service
членов, был важен! Другие члены (не показанные в моих примерах) ссылаются на Timer
в Runnable
s, вызывая Service
getter getTimer()
(также не показано). В этом получателе слушатель зарегистрирован, но еще не инициализирован, потому что он был объявлен / инициализирован после других членов, а не до их. Вздох ...
У меня есть класс Service
и внутренний класс Timer
, который выполняется в отдельном потоке. Этот таймер принимает прослушиватель тиков, который вызывается с фиксированными интервалами, когда таймер работает.
Суть этого такова:
public class Service {
private Timer timer;
Service() {
// more to follow in code snippets below where I demonstrate the issue I am facing
}
private static class Timer
implements Runnable {
private interface TickListener {
void onTick(Timer timer);
}
private TickListener tickListener;
public void setTickListener(TickListener tickListener) {
this.tickListener = tickListener;
}
public void start() {
new Thread(this).start();
}
@Override
public void run() {
while(keepThreadRunningCondition) {
if(tickListener != null) {
// to verify that Timer is actually running
// and tickListener is not null
// I actually log here
// and the log appears just fine in all cases
tickListener.onTick(this);
}
}
}
}
}
Теперь, когда я регистрирую слушателя тиков анонимно , вот так:
class Service {
private Timer timer;
Service() {
timer = new Timer();
timer.setTickListener(new Timer.TickListener() {
@Override
void onTick(Timer timer) {
// this gets called perfectly fine
}
});
}
}
... слушатель вызывается просто отлично, когда запускается таймер.
Однако, когда я регистрирую слушателя тика как члена моего Service
класс, вот так (я пробовал несколько различных перестановок public
, final
, volatile
, et c. также):
class Service {
private Timer timer;
private Timer.TickListener timerTickListener = new Timer.TickListener() {
@Override
void onTick(Timer timer) {
// this will NOT get called
}
};
Service() {
timer = new Timer();
timer.setTickListener(timerTickListener);
}
}
... the Слушатель не вызывается при запуске таймера.
Я подозреваю, что эта проблема связана с многопоточностью, потому что подобные настройки работают просто отлично, когда не охватывает разные потоки , но я не достаточно разбираюсь в многопоточности, чтобы точно понять, почему это не работает.
Можете ли вы пролить свет на эту проблему?
Это как-то связано с доступом объекты по ссылке в разных потоках, возможно? Или это что-то другое?