Handling concurrency in an application can be a tricky process
with many potential pitfalls. A solid grasp of the
fundamentals will go a long way to help minimize these issues.
Get started with understanding multi-threaded applications with
our Java Concurrency guide:
Spring 5 added support for reactive programming with the Spring
WebFlux module, which has been improved upon ever since. Get
started with the Reactor project basics and reactive programming
in Spring Boot:
Since its introduction in Java 8, the Stream API has become a
staple of Java development. The basic operations like iterating,
filtering, mapping sequences of elements are deceptively simple to
use.
But these can also be overused and fall into some common
pitfalls.
To get a better understanding on how Streams work and how
to combine them with other language features, check out our guide
to Java Streams:
Yes, Spring Security can be complex, from the more advanced
functionality within the Core to the deep OAuth support in the
framework.
I built the security material as two full courses - Core and
OAuth, to get practical with these more complex scenarios. We
explore when and how to use each feature and code through it on
the backing project.
Refactor Java code safely β and automatically β with
OpenRewrite.
Refactoring big codebases by hand is slow, risky, and easy to
put off. Thatβs where OpenRewrite comes in. The open-source
framework for large-scale, automated code transformations helps
teams modernize safely and consistently.
Each month, the creators and maintainers of OpenRewrite at
Moderne run live, hands-on training sessions β one for newcomers
and one for experienced users. Youβll see how recipes work, how to
apply them across projects, and how to modernize code with
confidence.
Join the next session,
bring your questions, and learn how to automate the kind of work
that usually eats your sprint time.
Handling concurrency in an application can be a tricky process
with many potential pitfalls. A solid grasp of the
fundamentals will go a long way to help minimize these issues.
Get started with understanding multi-threaded applications with
our Java Concurrency guide:
Daemon threads in Java are background threads that support other tasks, like system garbage collection, logging, system monitoring, and more. They run with lower priority and the Java Virtual Machine (JVM) terminates them after all user threads finish. Many JVM threads are daemon threads by default.
In this short article, weβll explore the main uses of daemon threads, and compare them to user threads. Additionally, weβll demonstrate how to programmatically create, run, and verify if a thread is a daemon thread.
2. Creating Daemon Threads
To create daemon threads, all we need to do is to call setDaemon() of the Thread API. In this example, weβll use the NewThread class which extends the Thread class:
NewThread daemonThread = new NewThread();
daemonThread.setDaemon(true);
daemonThread.start();
Any thread inherits the daemon status of the thread that created it. Since the main thread is a user thread, any thread created inside the main method is by default a user thread.
The method setDaemon() can only be called after the Thread object has been created and the thread hasnβt been started. An attempt to call setDaemon() while a thread is running throws an IllegalThreadStateException:
@Test(expected = IllegalThreadStateException.class)
public void whenSetDaemonWhileRunning_thenIllegalThreadStateException() {
NewThread daemonThread = new NewThread();
daemonThread.start();
daemonThread.setDaemon(true);
}
Additionally, we can use the isDaemon() method to check if a thread is a daemon thread:
@Test
public void whenCallIsDaemon_thenCorrect() {
NewThread daemonThread = new NewThread();
daemonThread.setDaemon(true);
daemonThread.start();
assertTrue(daemonThread.isDaemon());
NewThread userThread = new NewThread();
userThread.start();
assertFalse(userThread.isDaemon());
}
3. Differences Between Daemon and User Threads
So, we learned that Java offers two types of platform threads: user threads and daemon threads. While user threads are high-priority threads, daemon threads are low-priority threads whose only role is to provide services to user threads.
Letβs highlight other differences between daemon and user threads:
Feature
Daemon Threads
User Threads
Priority
Lower priority, mainly for background services
Higher priority, for main application tasks
JVM Behavior
JVM exits when only daemon threads are running
JVM continues running as long as any user thread is alive
Typical Use Cases
Garbage collection, system monitoring, etc.
Application logic, main program flow
Lifecycle
Automatically terminates when all user threads finish
Needs to be manually terminated
Since daemon threads are meant to serve user threads and are only needed while they are running, they wonβt prevent the JVM from exiting once all user threads have finished their execution.
Infinite loops typically exist in daemon threads and wonβt cause problems. This is happening because any code, including the finally blocks, wonβt be executed once all user threads have finished their execution. As a result,daemon threads arenβt recommended for I/O tasks.
However, there are exceptions to this rule. Poorly designed code in daemon threads can prevent the JVM from exiting. For example, calling Thread.join() on a running daemon thread can block the applicationβs shutdown.
4. Conclusion
In this quick tutorial, weβve seen what daemon threads are and what they can be used for in a few practical scenarios. Following that, we compared daemon threads to user threads, focusing on their differences.
The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
The Apache HTTP Client is a very robust library, suitable
for both simple and advanced use cases when testing HTTP
endpoints. Check out our guide covering basic request and
response handling, as well as security, cookies, timeouts, and
more:
Handling concurrency in an application can be a tricky process
with many potential pitfalls. A solid grasp of the
fundamentals will go a long way to help minimize these issues.
Get started with understanding multi-threaded applications with
our Java Concurrency guide:
Since its introduction in Java 8, the Stream API has become a
staple of Java development. The basic operations like iterating,
filtering, mapping sequences of elements are deceptively simple to
use.
But these can also be overused and fall into some common
pitfalls.
To get a better understanding on how Streams work and how
to combine them with other language features, check out our guide
to Java Streams:
Modern Java teams move fast β but codebases
donβt always keep up. Frameworks change, dependencies drift, and
tech debt builds until it starts to drag on delivery. OpenRewrite
was built to fix that: an open-source refactoring engine that
automates repetitive code changes while keeping developer intent
intact.
The monthly training series, led by the creators and maintainers
of OpenRewrite at Moderne, walks through real-world migrations and
modernization patterns. Whether youβre new to recipes or ready to
write your own, youβll learn practical ways to refactor safely and
at scale.
If youβve ever wished refactoring felt as natural β and as fast
β as writing code, this is a good
place to start.
Handling concurrency in an application can be a tricky process
with many potential pitfalls. A solid grasp of the
fundamentals will go a long way to help minimize these issues.
Get started with understanding multi-threaded applications with
our Java Concurrency guide: