Thread Methods in Java
The Thread class provides a collection of methods that allow you to inspect, start, coordinate, interrupt, and control the behavior of threads. You do not need to memorize every method immediately. What matters first is understanding what problem each method solves and when it should be used safely.
Some methods are fundamental to everyday multithreading, such as start(), currentThread(), sleep(), join(), interrupt(), and isAlive(). Others are mainly useful for inspection, debugging, or understanding thread behavior.
Important: Thread methods do not all "control" a thread in the same way. Modern Java encourages cooperative coordination rather than forcibly stopping or suspending threads.
Starting a Thread with start()
The start() method begins the execution of a new thread. It is the method you use when you want the Runnable task or Thread's run() method to execute on a separate thread.
Thread worker = new Thread(() -> {
System.out.println(
"Running on: "
+ Thread.currentThread().getName()
);
});
worker.start();
Calling start() does not mean the new thread executes immediately. It makes the thread eligible for execution, after which the JVM and operating system scheduler determine when it runs.
Remember: start() creates a new execution path. Calling run() directly does not.
Getting the Current Thread with currentThread()
The static method Thread.currentThread() returns the Thread object representing the thread that is currently executing the code.
public class CurrentThreadDemo {
public static void main(String[] args) {
Thread current = Thread.currentThread();
System.out.println(
"Name: " + current.getName()
);
System.out.println(
"ID: " + current.threadId()
);
}
}
This method is particularly useful when debugging multithreaded applications because it lets you identify which thread is executing a particular piece of code.
Getting a Thread's Name with getName()
The getName() method returns the name assigned to a thread.
Thread thread = new Thread(() -> {
System.out.println(
Thread.currentThread().getName()
);
}, "Report-Worker");
thread.start();
Meaningful names are especially valuable when examining logs or thread dumps in production systems.
Changing a Thread's Name with setName()
The setName() method changes a thread's name.
Thread thread = new Thread(() -> {
System.out.println(
Thread.currentThread().getName()
);
});
thread.setName("Email-Worker");
thread.start();
Thread names are primarily useful for identification and diagnostics. They do not change how the thread is scheduled.
Pausing Execution with sleep()
The static Thread.sleep() method pauses the currently executing thread for a specified duration.
try {
System.out.println("Task started");
Thread.sleep(2000);
System.out.println("Task resumed");
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
During the sleep period, the thread enters the TIMED_WAITING state.
Important: sleep() pauses the current thread, but it does not release monitors or intrinsic locks that the thread already holds.
Waiting for Another Thread with join()
The join() method allows one thread to wait for another thread to finish.
Thread worker = new Thread(() -> {
System.out.println("Worker started");
});
worker.start();
try {
worker.join();
System.out.println("Worker completed");
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
In this example, the main thread waits until the worker thread terminates before continuing.
This is useful when one operation depends on the completion of another operation.
Timed join()
Java also provides a timed version of join(). It allows the current thread to wait for a maximum amount of time rather than indefinitely.
try {
worker.join(2000);
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
After the specified waiting period, the calling thread can continue even if the target thread has not yet completed.
Checking Whether a Thread Is Alive
The isAlive() method returns true if a thread has been started and has not yet terminated.
Thread worker = new Thread(() -> {
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
System.out.println(worker.isAlive());
worker.start();
System.out.println(worker.isAlive());
try {
worker.join();
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println(worker.isAlive());
The first check is normally false because the thread has not started. After starting, it can be true while execution is in progress. After termination, it becomes false again.
Inspecting the Thread State with getState()
The getState() method returns the thread's current state as a value from Thread.State.
Thread worker = new Thread(() -> {
System.out.println("Working");
});
System.out.println(
worker.getState()
);
worker.start();
Before start(), the state is normally NEW. After starting, it can move through RUNNABLE, WAITING, TIMED_WAITING, BLOCKED, and finally TERMINATED depending on what the thread is doing.
Interrupting a Thread with interrupt()
The interrupt() method is one of the most misunderstood Thread methods. It does not forcibly kill a thread. Instead, it communicates an interruption request.
Thread worker = new Thread(() -> {
try {
while (true) {
System.out.println("Working");
Thread.sleep(500);
}
}
catch (InterruptedException e) {
System.out.println(
"Worker interrupted"
);
Thread.currentThread().interrupt();
}
});
worker.start();
try {
Thread.sleep(2000);
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
worker.interrupt();
If the worker is sleeping when interrupt() is called, sleep() can respond by throwing InterruptedException.
Key idea: Interruption is generally cooperative. The interrupted thread should decide how to respond to the interruption according to the task's requirements.
Checking the Interrupt Status with isInterrupted()
The instance method isInterrupted() checks whether a thread's interrupt status is set without clearing it.
Thread worker = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("Working");
break;
}
});
worker.start();
worker.interrupt();
This method is useful when a thread needs to periodically check whether it has received an interruption request.
Checking the Current Thread's Interrupt Status with interrupted()
The static method Thread.interrupted() checks the interrupt status of the current thread and clears that status if it was set.
if (Thread.interrupted()) {
System.out.println(
"Current thread was interrupted"
);
}
Important distinction: isInterrupted() checks a specific Thread object without clearing its interrupt status. Thread.interrupted() checks the current thread and clears the status.
Getting a Thread's ID
The threadId() method returns the thread's identifier.
Thread current = Thread.currentThread();
System.out.println(
"Thread ID: " + current.threadId()
);
Thread IDs can be useful when correlating runtime information with logs and diagnostic tools.
Getting and Setting Thread Priority
A Thread has a priority value that can be inspected using getPriority() and changed using setPriority().
Thread worker = new Thread(() -> {
System.out.println("Worker running");
});
System.out.println(
"Default priority: "
+ worker.getPriority()
);
worker.setPriority(Thread.NORM_PRIORITY);
System.out.println(
"Current priority: "
+ worker.getPriority()
);
Java defines the constants MIN_PRIORITY, NORM_PRIORITY, and MAX_PRIORITY. Thread priorities provide scheduling hints rather than strict execution guarantees.
Setting a Thread as a Daemon
The setDaemon() method marks a thread as a daemon thread. A daemon thread is generally used for background support work and does not prevent the JVM from shutting down once all non-daemon threads have terminated.
Thread worker = new Thread(() -> {
while (true) {
System.out.println("Background work");
}
});
worker.setDaemon(true);
worker.start();
The daemon status must be configured before the thread is started.
Important: Daemon status is not a mechanism for safely terminating work. When the JVM exits because no non-daemon threads remain, daemon threads do not keep the JVM alive to finish their work.
Checking Daemon Status
The isDaemon() method tells you whether a Thread is configured as a daemon thread.
Thread worker = new Thread(() -> {
System.out.println("Background task");
});
worker.setDaemon(true);
System.out.println(
worker.isDaemon()
);
Deprecated Thread Control Methods
Older Java versions provided methods such as stop(), suspend(), and resume() for forcibly controlling threads. These methods are deprecated because they can leave shared data in inconsistent states and create difficult synchronization problems.
Professional rule: Do not design modern Java applications around forcibly stopping, suspending, or resuming threads. Prefer cooperative cancellation through interruption and appropriate concurrency abstractions.
Commonly Used Thread Methods
| Method | Purpose |
|---|---|
| start() | Starts a new thread of execution. |
| run() | Contains the task executed by the thread; direct invocation does not create a new thread. |
| currentThread() | Returns the thread currently executing the code. |
| sleep() | Pauses the current thread for a specified duration. |
| join() | Waits for another thread to terminate. |
| interrupt() | Requests interruption of a thread. |
| isInterrupted() | Checks a thread's interrupt status without clearing it. |
| interrupted() | Checks and clears the current thread's interrupt status. |
| isAlive() | Checks whether a started thread has not yet terminated. |
| getState() | Returns the thread's current Thread.State. |
| getName() | Returns the thread's name. |
| setName() | Changes the thread's name. |
| threadId() | Returns the thread's identifier. |
| setDaemon() | Marks a thread as a daemon before it is started. |
| isDaemon() | Checks whether the thread is a daemon thread. |
Example: Combining Several Thread Methods
public class ThreadMethodsDemo {
public static void main(String[] args) {
Thread worker = new Thread(() -> {
System.out.println(
"Worker: "
+ Thread.currentThread().getName()
);
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
System.out.println(
"Worker interrupted"
);
Thread.currentThread().interrupt();
}
});
worker.setName("Data-Worker");
System.out.println(
"State before start: "
+ worker.getState()
);
worker.start();
System.out.println(
"Alive: "
+ worker.isAlive()
);
try {
worker.join();
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println(
"Final state: "
+ worker.getState()
);
System.out.println(
"Alive after completion: "
+ worker.isAlive()
);
}
}
This example demonstrates a realistic sequence: configure the thread, start it, inspect its status, wait for completion, and finally inspect its terminated state.
Common Beginner Mistakes
- Calling run() directly when a new thread is required.
- Assuming sleep() releases locks held by the sleeping thread.
- Using interrupt() as though it forcibly kills a thread.
- Ignoring InterruptedException without considering the interruption policy of the application.
- Assuming thread priority guarantees execution order.
- Setting daemon status after a thread has already been started.
- Using deprecated methods such as stop(), suspend(), or resume().
Best Practices
- Use start() to create a separate execution path.
- Use join() when one task genuinely needs another thread to finish first.
- Use interruption as a cooperative cancellation signal.
- Restore the interrupt status when catching InterruptedException if the current method cannot fully handle the interruption.
- Use descriptive thread names for production diagnostics.
- Treat thread priority as a scheduling hint, not a correctness mechanism.
- Prefer higher-level concurrency utilities when they provide a cleaner solution than manually coordinating raw Thread objects.
Interview Insights
Question: What does sleep() do?
It pauses the currently executing thread for a specified duration. During that period the thread is generally in TIMED_WAITING. It does not release monitors held by that thread.
Question: What does join() do?
It causes the calling thread to wait for another thread to terminate. A timed version can limit how long the caller waits.
Question: Does interrupt() stop a thread?
No. It requests interruption. The target thread must respond appropriately, either by handling an InterruptedException or by checking its interrupt status.
Question: What is the difference between isInterrupted() and interrupted()?
isInterrupted() checks a particular thread's interrupt status without clearing it. Thread.interrupted() checks the current thread's status and clears it when set.
Question: Does thread priority guarantee which thread executes first?
No. Priority can influence scheduling behavior, but application correctness must never depend on a guaranteed execution order based solely on thread priority.
Quick Revision
| Method | Core Idea |
|---|---|
| start() | Starts a new execution path. |
| currentThread() | Returns the currently executing Thread. |
| sleep() | Temporarily pauses the current thread. |
| join() | Waits for another thread to finish. |
| interrupt() | Sends an interruption request. |
| isInterrupted() | Checks interrupt status without clearing it. |
| interrupted() | Checks and clears the current thread's interrupt status. |
| isAlive() | Checks whether a started thread has not terminated. |
| getState() | Inspects the current Thread.State. |
| setName() | Assigns a useful diagnostic name. |
| setDaemon() | Marks a thread as a daemon before starting it. |
Thread methods become much easier to remember when you learn them by purpose rather than as an isolated list. start() begins execution, sleep() pauses, join() coordinates completion, interrupt() requests cancellation, and inspection methods such as getState() and isAlive() help you understand what a thread is doing. With these tools in place, the next chapter can focus on Thread Priorities and what priority does—and does not—guarantee.
