Expand Authors Top

If you have a few years of experience in the Java ecosystem and you’d like to share that with the community, have a look at our Contribution Guidelines.

November Discount Launch 2022 – Top
We’re finally running a Black Friday launch. All Courses are 30% off until next Friday:

>> GET ACCESS NOW

Expanded Audience – Frontegg – Security (partner)
announcement - icon User management is very complex, when implemented properly. No surprise here.

Not having to roll all of that out manually, but instead integrating a mature, fully-fledged solution - yeah, that makes a lot of sense.
That's basically what Frontegg is - User Management for your application. It's focused on making your app scalable, secure and enjoyable for your users.
From signup to authentication, it supports simple scenarios all the way to complex and custom application logic.

Have a look:

>> Elegant User Management, Tailor-made for B2B SaaS

November Discount Launch 2022 – TEMP TOP (NPI)
We’re finally running a Black Friday launch. All Courses are 30% off until next Friday:

>> GET ACCESS NOW

1. Overview

In this quick tutorial, we're going to see why we shouldn't start a thread inside a constructor.

First, we'll briefly introduce the publication concept in Java and JVM. Then, we'll see how this concept affects the way we start threads.

2. Publication and Escape

Every time we make an object available to any other code outside of its current scope, we basically publish that object. For instance, publishing happens when we return an object, store it into a public reference, or even pass it to another method.

When we publish an object that we shouldn't have, we say that the object has escaped.

There are many ways that we can let an object reference escape, such as publishing the object before its full construction. As a matter of fact, this is one of the common forms of escape: when the this reference escapes during object construction.

When the this reference escapes during construction, other threads may see that object in an improper and not fully-constructed state. This, in turn, can cause weird thread-safety complications.

3. Escaping with Threads

One of the most common ways of letting the this reference escape is to start a thread in a constructor. To better understand this, let's consider an example:

public class LoggerRunnable implements Runnable {

    public LoggerRunnable() {
        Thread thread = new Thread(this); // this escapes
        thread.start();
    }

    @Override
    public void run() {
        System.out.println("Started...");
    }
}

Here, we explicitly pass the this reference to the Thread constructor. Therefore, the newly started thread might be able to see the enclosing object before its full construction is complete. In concurrent contexts, this may cause subtle bugs.

It's also possible to pass the this reference implicitly:

public class ImplicitEscape {
    
    public ImplicitEscape() {
        Thread t = new Thread() {

            @Override
            public void run() {
                System.out.println("Started...");
            }
        };
        
        t.start();
    }
}

As shown above, we're creating an anonymous inner class derived from the Thread. Since inner classes maintain a reference to their enclosing class, the this reference again escapes from the constructor.

There's nothing inherently wrong with creating a Thread inside a constructor. However, it's highly discouraged to start it immediately, as most of the time, we end up with an escaped this reference, either explicitly or implicitly.

3.1. Alternatives

Instead of starting a thread inside a constructor, we can declare a dedicated method for this scenario:

public class SafePublication implements Runnable {
    
    private final Thread thread;
    
    public SafePublication() {
        thread = new Thread(this);
    }

    @Override
    public void run() {
        System.out.println("Started...");
    }
    
    public void start() {
        thread.start();
    }
};:

As shown above, we still publish the this reference to the Thread. However, this time, we start the thread after the constructor returns:

SafePublication publication = new SafePublication();
publication.start();

Therefore, the object reference does not escape to another thread before its full construction.

4. Conclusion

In this quick tutorial, after a brief introduction to the safe publication, we saw why we shouldn't start a thread inside a constructor.

More detailed information about the publication and escape in Java can be found in the Java Concurrency in Practice book.

As usual, all the examples are available over on GitHub.

November Discount Launch 2022 – Bottom
We’re finally running a Black Friday launch. All Courses are 30% off until next Friday:

>> GET ACCESS NOW

Generic footer banner
Comments are closed on this article!