I understand that in general it is a bad idea to start a new thread in a constructor because it could let this escape before it is fully constructed. For example:
public final class Test {
private final int value;
public Test(int value) throws InterruptedException {
start();
this.value = value;
}
private void start() throws InterruptedException {
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Construction OK = " + Boolean.toString(Test.this.value == 5));
}
}).start();
}
}
public static void main(String[] args) throws InterruptedException {
Test test = new Test(5);
}
}
This prints (obviously not the same every run):
Construction OK = false
Construction OK = false
Construction OK = false
Construction OK = false
Construction OK = false
Construction OK = false
Construction OK = false
Construction OK = true
Construction OK = true
Construction OK = true
Now IF the start method is the last statement of the constructor AND reordering is prevented by using a synchronized block around the final value initialisation, is there still a risk associated with starting threads from the constructor?
public Test(int value) throws InterruptedException {
synchronized (new Object()) { // to prevent reordering + no deadlock risk
this.value = value;
}
start();
}
EDIT
I don’t think this has been asked before in the sense that the question is more specific than just “Can I start threads in a constructor”: the threads are started in the last statement of the constructor which means the object construction is finished (as far as I understand it).
In this particular case I would consider marking
valueasvolatile(or useAtomicBoolean) and start the threads after the value is set:If going for this slightly dodgy solution, I would make the class
finalas well, to avoid the problem described by Andreas_D.Regarding your edit:
That’s right, but consider the following scenario:
Your test-threads are slightly more complex, and accesses a list
testListof tests. Now if you dothe thread started in the constructor may not find the associated test in the list, because it has not yet been added. This is avoided by instead doing
Related question: