Looping in Threads

Consider the following two designs of run method:

Approach A

public void run() {
    do {
        //do something
    } while (condition);
}

Approach B

public void run() {

    //do something...

    if (condition) {
       new Thread(this).start();
    }
}

The second approach seems cleaner to me, after some debate, I have been told it's not a good idea to use approach two.

Question:

  1. What are reasons (if there is any) that I shouldn't be using approach 2?
17

5 Answers

You have two things here. A loop, and a method that continuously runs itself again in a new thread until a condition is met (not a loop).

If you need a loop, you would choose the standard normal loop that everyone understands and works perfectly.

If you need to write a weird piece of code that creates new threads for no reason, and makes other developers doubt your skills and understanding, you would go for option B.

There's absolutely no sense in your choice B unless there would be something additional like a queue or ThreadPoolExecutor involved for re-invoking the method, so the method would add this at the end for invocation at a later time, sort of like a "lazy loop".

1

Because approach B uses one more thread than approach A. Creating threads is expensive, for a number of reasons @see Why is creating a Thread said to be expensive?

Approach A is also a little clearer to the reader, IMO. The simplest option usually is.

4

The 2nd option creates a new thread every time it is iterated, so it ends up being unnecessarily costly, especially when option A does the same thing but doesn't create new threads for every iteration.

The only good use-case I can find for Pattern B is if there is a significant delay before you want to re-run the method. For example for some kind of polling system that is supposed to run every X minutes until the system is being shut down.

In that case, using a scheduler instead of a Thread.sleep(fiveMinutes) makes sense to avoid tieing up resources unnecessarily (maybe you are holding on to a database connections or such).

Note that in that case, you'd be using a scheduler, not just Thread#start, so I am allowing for a rather liberal interpretation of Pattern B.

7

They will behave very differently.

The first solution will loop until condition is false and then terminate.

The second solution will start a new thread and die until condition is false. It will likely accomplish what you want to do but it will waste a lot of resources allocating and destroying new threads.

Here's an example that loops over 5 values and prints the value and current thread name:

Loop:

Runnable loop = new Runnable() {

    int i = 0;

    @Override
    public void run() {
        do {
            System.out.printf("%s: %s%n", Thread.currentThread().getName(), i);
            i++;
        } while(i < 5);
    }
};
loop.run();

main: 0
main: 1
main: 2
main: 3
main: 4

Threaded:

Runnable thread = new Runnable() {

    int i = 0;

    @Override
    public void run() {
        System.out.printf("%s: %s%n", Thread.currentThread().getName(), i);
        i++;
        if(i < 5) {
            new Thread(this).start();
        }
    }
};
thread.run();

main: 0
Thread-0: 1
Thread-1: 2
Thread-2: 3
Thread-3: 4

As you can see, the threaded example prints each line on a different thread which is very wasteful and probably not what you want to accomplish.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Sarah Jenkins

Sarah Jenkins

Senior Technology Editor & AI Specialist

Sarah Jenkins is a veteran tech journalist with over 12 years of experience covering artificial intelligence, mobile innovations, and digital ethics. Her insights have appeared in leading technology publications worldwide.

Share this article
Twitter Facebook Pinterest