smithaiw
smithaiw

Reputation: 107

Are there performance implications to creating a Thread and never starting it?

I'm working on an existing Java codebase which has an object that extends Thread, and also contains a number of other properties and methods that pertain to the operation of the thread itself. In former versions of the codebase, the thread was always an actual, heavyweight Thread that was started with Thread.start, waited for with Thread.join, and the like.

I'm currently refactoring the codebase, and in the present version, the object's Thread functionality is not always needed (but the object itself is, due to the other functionality contained in the object; in many cases, it's usable even when the thread itself is not running). So there are situations in which the application creates these objects (which extend Thread) and never calls .start() on them, purely using them for their other properties and methods.

In the future, the application may need to create many more of these objects than previously, to the point where I potentially need to worry about performance. Obviously, creating and starting a large number of actual threads would be a performance nightmare. Does the same thing apply to Thread objects that are never started? That is, are any operating system resources, or large Java resources, required purely to create a Thread? Or are the resources used only when the Thread is actually .started, making unstarted Thread objects safe to use in quantity? It would be possible to refactor the code to split the non-threading-related functionality into a separate function, but I don't want to do a large refactoring if it's entirely pointless to do so.

I've attempted to determine the answer to this with a few web searches, but it's hard to aim the query because search engines can't normally distinguish a Thread object from an actual Java thread.

Upvotes: 1

Views: 145

Answers (3)

GhostCat
GhostCat

Reputation: 140573

As the others have pointed out: performance isn't a problem here.

I would focus much more on the "good design" approach. It simply doesn't make (much, any?) sense to extend Thread when you do not intend to ever invoke start(). And you see: you write code to communicate your intentions.

Extending Thread without using it as thread, that only communicates confusion. Every new future reader of your code will wonder "why is that"?

Therefore, focus on getting to a straight forward design. And I would go one step further: don't just turn to Runnable, and continuing to use threads. Instead: learn about ExecutorServices, and how to submit tasks, and Futures, and all that.

"Bare iron" Threads (and Runnables) are like 20 year old concepts. Java has better things to offer by now. So, if you are really serious about improving your code base: look into these new abstraction concepts to figure where they would make sense to be used.

Upvotes: 2

Peter Lawrey
Peter Lawrey

Reputation: 533730

You can create about 1.5 million of these objects per GB of memory.

import java.util.LinkedList;
import java.util.List;

class A {
    public static void main(String[] args) {
        int count = 0;
        try {
            List<Thread> threads = new LinkedList<>();
            while (true) {
                threads.add(new Thread());
                if (++count % 10000 == 0)
                    System.out.println(count);
            }
        } catch (Error e) {
            System.out.println("Got " + e + " after " + count + " threads");
        }
    }
}

using -Xms1g -Xmx1g for Oracle Java 8, the process grinds to halt at around

1 GB - 1780000
2 GB - 3560000
6 GB - 10690000

The object uses a bit more than you might expect from reading the source code, but it's still about 600 bytes each.

NOTE: Throwable also use more memory than you might expect by reading the Java source. It can be 500 - 2000 bytes more depending on the size of the stack at the time it was created.

Upvotes: 1

Davide
Davide

Reputation: 136

You could implement Runnable instead of extending Thread.

public class MyRunnableClass implements Runnable {

    // Your stuff...

    @Override
    public void run() {
        // Thread-related stuff...
    }

}

Whenever you need to run your Object to behave as a Thread, simply use:

Thread t = new Thread(new MyRunnableClass());
t.start();

Upvotes: 4

Related Questions