1

In my Java application I have a Runnable such as:

this.runner = new Runnable({
    @Override
    public void run() {
        // do something that takes roughly 5 seconds.
    }
});

I need to run this roughly every 30 seconds (although this can vary) in a separate thread. The nature of the code is such that I can run it and forget about it (whether it succeeds or fails). I do this as follows as a single line of code in my application:

(new Thread(this.runner)).start()

Now, this works fine. However, I'm wondering if there is any sort of cleanup I should be doing on each of the thread instances after they finish running? I am doing CPU profiling of this application in VisualVM and I can see that, over the course of 1 hour runtime, a lot of threads are being created. Is this concern valid or is everything OK?

N.B. The reason I start a new Thread instead of simply defining this.runner as a Thread, is that I sometimes need to run this.runner twice simultaneously (before the first run call has finished), and I can't do that if I defined this.runner as a Thread since a single Thread object can only be run again once the initial execution has finished.

ABC
  • 693
  • 1
  • 10
  • 22
  • 1
    I would advise to look at `ScheduledThreadPoolExecutor` pool and its `scheduleAtFixedRate` method. This way you do not have to deal with threads manually and let pool manage threads for you. – Michał Krzywański Oct 09 '19 at 07:32

2 Answers2

2

Java objects that need to be "cleaned up" or "closed" after use conventionally implement the AutoCloseable interface. This makes it easy to do the clean up using try-with-resources. The Thread class does not implement AutoCloseable, and has no "close" or "dispose" method. So, you do not need to do any explicit clean up.

However

(new Thread(this.runner)).start()

is not guaranteed to immediately start computation of the Runnable. You might not care whether it succeeds or fails, but I guess you do care whether it runs at all. And you might want to limit the number of these tasks running concurrently. You might want only one to run at once, for example. So you might want to join() the thread (or, perhaps, join with a timeout). Joining the thread will ensure that the thread will completes its computation. Joining the thread with a timeout increases the chance that the thread starts its computation (because the current thread will be suspended, freeing a CPU that might run the other thread).

However, creating multiple threads to perform regular or frequent tasks is not recommended. You should instead submit tasks to a thread pool. That will enable you to control the maximum amount of concurrency, and can provide you with other benefits (such as prioritising different tasks), and amortises the expense of creating threads.

You can configure a thread pool to use a fixed length (bounded) task queue and to cause submitting threads to execute submitted tasks itself themselves when the queue is full. By doing that you can guarantee that tasks submitted to the thread pool are (eventually) executed. The documentation of ThreadPool.execute(Runnable) says it

Executes the given task sometime in the future

which suggests that the implementation guarantees that it will eventually run all submitted tasks even if you do not do those specific tasks to ensure submitted tasks are executed.

Raedwald
  • 46,613
  • 43
  • 151
  • 237
  • Another question - if it's a latency sensitive application and I need the thread to run NOW, is the thread pool the right approach? – ABC Oct 09 '19 at 10:47
  • If you **really** need something to run something *now*, the only reliable approach is to run it yourself (in the current thread), because you can not guarantee that there is another CPU to run the task concurrently with the current thread. – Raedwald Oct 09 '19 at 11:01
  • Let me reformulate. How can I run a `Runnable` in a separate thread, without blocking the main thread, if my desire/requirement is to make sure it executes as quickly as possible? Should I use an ExecutorService or just do `new Thread(..)` or some other approach? Thanks. – ABC Oct 09 '19 at 11:06
  • *As quickly as possible* is too vague. Many things are possible. It comes down to how much effort (cost) you are willing to expend. *As quickly as possible* i was not part of your posted question; you ought to ask a different question is you are interested in doing that. – Raedwald Oct 09 '19 at 11:10
  • 1
    @ABC, A task usually will be executed more quickly if you submit it to a pool instead of creating a new thread. Thread creation and destruction is expensive. That's the whole point of thread pools---to avoid that overhead by re-using threads. – Solomon Slow Oct 10 '19 at 17:25
1

I recommend you to look at the Concurrency API. There are numerous pre-defined methods for general use. By using ExecutorService you can call the shutdown method after submitting tasks to the executor which stops accepting new tasks, waits for previously submitted tasks to execute, and then terminates the executor. For a short introduction: https://www.baeldung.com/java-executor-service-tutorial

Joshgun
  • 372
  • 3
  • 16