Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Starting a thread as the last statement of the constructor of a final class

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).

like image 453
assylias Avatar asked Dec 08 '25 21:12

assylias


1 Answers

Yes there is, because Test could be subclassed and then start() will be executed before the instance is created. The subclasses constructor may have something more to do.

So the class should be final at least.

like image 82
Andreas Dolk Avatar answered Dec 10 '25 09:12

Andreas Dolk