What does "When the inner EventListener instance is published,so is the enclosing ThisEscape instance." mean?
This quote is from 《java Concurrency in Practice》
public class ThisEscape {
public ThisEscape(EventSource source)
{
source.registerListener(
new EventListener(){
public void onEvent(Event e)
{
doSomething(e);
}
}
);
}
}
ThisEscape
instance is published during construction because doSomething
is a method of ThisEscape
, which can cause unforeseen problems.
A simple code example, when a event occurs, the ThisEscape
object has not yet been built, but since this ThisEscape
is registered with the EventSource
, then onSomeThing
method is triggered, and an NPE
is generated because ThisEscape#data
has not yet been initialized:
public class ThisEscape {
static class EventSource {
private List<EventListener> eventListeners = new ArrayList<>();
public void registerListener(EventListener eventListener) {
eventListeners.add(eventListener);
}
public void eventHappen(Event event) {
eventListeners.forEach(eventListener -> {
eventListener.onEvent(event);
});
}
}
static class Event {
public String eventString;
public Event(String eventString) {
this.eventString = eventString;
}
}
interface EventListener {
void onEvent(Event e);
}
private List<String> data;
public void doSomething(Event e) {
data.add(e.eventString);
}
public ThisEscape(EventSource source) {
source.registerListener(
new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
}
);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.data = new ArrayList<>();
}
public static void main(String[] args) {
EventSource eventSource = new EventSource();
new Thread(() -> {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
eventSource.eventHappen(new Event("hello"));
}).start();
ThisEscape thisEscape = new ThisEscape(eventSource);
}
}