What Every Java Developer Should Know About Thread, Runnable, and Thread Pool
Most important information about Thread, Runnable, and Thread Pool notions in Java with clear examples, infographics, and explanations.
Join the DZone community and get the full member experience.
Join For FreeMultithreading Is Most Complex And Biggest Part Of Java
Multithreading chapters are the most difficult to understand and use in Java. Unfortunately, there are not that many sources where you can get all the answers. Meanwhile, concurrency knowledge is critically important. In this article, I explain the core aspects of multithreading that every Java developer has to know. In this part, we start with the Thread and Runnable subject.
Why Is Concurrency Knowledge So Critical?
You Can't Get Senior Java Job Without Good Knowledge Of Multithreading
Multithreading knowledge almost certainly is the subject of interviews for senior Java positions. Without a clear understanding of multithreading with and without hands-on experience, you most likely will fail.
Almost Every Production Application Uses Multithreading Paradigm
In practice in real projects, you will use application servers or their alternatives. All of them are based on multithreading solutions like thread pools, etc. Any proper implementation on top of it requires concurrency consistency.
Thread and Runnable Definitions
Multithreading is based on Thread and Runnable. Thread is a class that starts new independent activity and performs instructions supplied by Runnable.
Thread is an entity that is attached to the OS so this is why it's a heavy class. Meanwhile Runnable is just a set of instructions — so this is why it's lightweight.
How to Execute New Thread
Thread can execute instructions inside the current running thread by using Run()
method. In order to run instructions in a new activity, Thread provides Start()
method.
(new Thread()).run(); // run in current thread
(new Thread()).start(); // run in new thread
How to Reuse Thread
Thread can perform many runnables inside of it. Here is an article with more details. Here you can see a very short example with many runnables (tasks) run inside one single thread:
List<Runnable> tasks = new ArrayList<Runnable>();
(new Thread(() -> {
for (Runnable task : tasks) {
task.run();
}
})).start();
How to Stop Thread
You can't just stop()
or suspend()
thread. These methods are deprecated. You have to take care about interruption design using isAlive()
or isInterrupted()
(new Thread(() -> {
while(true){
// process a peace of logic
if(Thread.currentThread().isInterrupted()){
//handle exiting
break;
}
}
})).start();
Thread Daemon
Thread can be a daemon. Daemon threads are interrupted instantly even the final part won't be executed. So such threads can be attached to resources. Otherwise, they can be the reason for resource or/and memory leaks.
Thread thread = (new Thread(() -> {
try {
// working with resource
} finally {
// resource.close(); - might won't work because finally if
// deamon been interrupted
}
}));
thread.setDaemon(true);
thread.start();
How To Use Thread Pool
As long as the Thread instance is heavy it makes sense to reuse the same Thread using ThreadPool class. You can use different ThreadPool implementations depending on your thread.
Fixed Thread Pool
FixedThreadPool is a simple pool with a predefined number of threads. The number of threads won't be changed during. It makes sense to use it:
Cached Thread Pool
Opposite to Fixed Thread Pool, this one can increase the number of threads dynamically when more tasks are added. Each newly created thread will be alive while it's used otherwise it will be removed after 60 seconds of idle.
How To Define Number Of Threads In Thread Pool
In order to use the best Thread Pool for your application you need to understand next things:
- If your thread does a lot of computation like video rendering, encryption, etc., then it eats processes that run that thread.
- If your thread runs not related to CPU activity like networking calls, memory calls, etc., then it won't consume the CPU that runs its thread.
Relying on this knowledge you might make the next conclusions:
- Having high CPU consumable tasks don't allocate more threads than CPU cores
- Having low CPU consumable tasks you can have a number of threads more than CPU cores (but proportion depends on the specific situation).
Conclusion
This article highlights just the main thing about Thread, Runnable, and Thread Pool notions but doesn't cover it completely. There are still many aspects that might play an important role. I hope you liked the infographics I used. Please leave your feedback if you think that I missed something critically important related to this subject. Thanks for reading!
Opinions expressed by DZone contributors are their own.
Comments