Files
2026-07-19 06:12:05 +03:30

4.9 KiB

start() vs run()

Output

The output will be similar to:

Calling run()
Running in: main
Calling start()
Running in: Thread-2

(The exact order of the last two lines may vary slightly because start() creates a new thread that runs independently.)

Why?

When t1.run() is called, the run() method is executed like a normal method call. It does not create a new thread. Since main() is the thread currently executing the code, Thread.currentThread().getName() returns main.

When t2.start() is called, Java creates a new thread and the JVM schedules that thread to execute the run() method. Because the new thread was created with the name "Thread-2", the output shows Thread-2 as the executing thread.

Difference between start() and run()

The main difference is that start() creates a new thread of execution, while run() only executes the method in the current thread.

  • Calling run() directly does not start a new thread. The code runs sequentially in the same thread that called it.
  • Calling start() creates a new thread and then internally calls the run() method on that new thread.
  • start() allows multiple threads to run concurrently, while run() behaves like a normal method call.

In this example, t1.run() runs inside the main thread, but t2.start() runs inside a separate thread named Thread-2.

2.Daemon Threads

Output

The output will usually be:

Main thread ends.

Sometimes it may also print one or more lines like:

Daemon thread running...
Main thread ends.

The exact output depends on the timing of the JVM shutting down.

Why?

The thread is marked as a daemon thread using:

thread.setDaemon(true);

Daemon threads run in the background and do not prevent the JVM from exiting. When the main thread finishes, there are no remaining non-daemon threads, so the JVM terminates. As a result, the daemon thread may be stopped before it completes its loop of printing messages 20 times.

What happens if thread.setDaemon(true) is removed?

If setDaemon(true) is removed, the thread becomes a normal (user) thread. The JVM will wait for this thread to finish before shutting down.

The output will look something like:

Main thread ends.
Daemon thread running...
Daemon thread running...
Daemon thread running...
...

The daemon thread will continue running until the loop completes, even though the main thread has already finished.

Real-life use cases of daemon threads

Daemon threads are useful for background tasks that should automatically stop when the main application ends. Some examples include:

  • Garbage collection: The JVM uses background daemon threads to manage memory cleanup.
  • Background monitoring: Applications can use daemon threads to monitor system resources, logs, or application status.
  • Auto-save features: A text editor or IDE might use a daemon thread to periodically save temporary data.
  • Cache cleanup: A server application might run a daemon thread to remove expired cache entries.
  • Scheduled background tasks: Tasks like checking for updates or refreshing data can run as daemon threads.

Daemon threads are mainly used for tasks that support the main application but are not essential for the application to finish running.

3. A Shorter Way to Create Threads

Output

The output will be:

Thread is running using a ...!

The message is printed from the new thread created by calling thread.start().

What is the () -> { ... } syntax called?

The () -> { ... } syntax is called a lambda expression in Java.

A lambda expression is a shorter way to write an implementation of a functional interface. In this example, it replaces the need to create a separate class that implements Runnable.

The code:

() -> {
    System.out.println("Thread is running using a ...!");
}

acts as the implementation of the Runnable interface's run() method.

How is this different from creating a class that extends Thread or implements Runnable?

Using a lambda expression makes the code shorter and easier to read because it avoids creating an extra class.

With implements Runnable, we normally create a separate class:

class MyRunnable implements Runnable {
    public void run() {
        System.out.println("Thread running");
    }
}

With a lambda expression, the same idea can be written directly:

Thread thread = new Thread(() -> {
    System.out.println("Thread running");
});

Extending Thread means creating a new class that inherits from the Thread class and overrides the run() method. This gives more control over the thread object but is less flexible because Java only allows a class to extend one class.

Using Runnable or a lambda expression is generally preferred because it separates the task being performed from the thread itself and allows the code to be more reusable.