Files
2026-06-03 11:13:40 +03:30

4.3 KiB
Raw Permalink Blame History

Question 1: start() vs run()

What output do you get from the program?

The first call (t1.run()) prints Running in: main because it executes on the main thread directly — no new thread is created. The second call (t2.start()) properly spawns a new thread, so it prints Running in: Thread-2.

The Thread.sleep(100) between the two calls ensures t2's output isn't interleaved with the first, but the ordering of the second line is still technically non-deterministic (it will almost always appear after "Calling start()").

What's the difference between start() and run()?

run() start()
Execution Runs on the calling thread (like a normal method call) Spawns a new OS thread and runs run() on it
Concurrency None — sequential, blocking Concurrent — the calling thread continues immediately
Thread name Uses the calling thread's name (main) Uses the new thread's name (Thread-2)
Thread lifecycle Does not transition the thread to RUNNABLE state Properly starts the thread lifecycle

Calling run() directly is just a regular method call. Only start() actually creates a new thread.


Question 2: Daemon Threads

What output do you get from the program?

Main thread ends.
Daemon thread running...
Daemon thread running...
(possibly a few more lines, then the program exits abruptly)

The exact number of "Daemon thread running..." lines is non-deterministic — typically 0 to 2. The JVM shuts down as soon as the main thread finishes, which kills all remaining daemon threads immediately, regardless of what they're doing.

What happens if you remove thread.setDaemon(true)?

The thread becomes a regular (non-daemon) user thread. The JVM will not exit until all user threads complete. In this case, the loop runs all 20 iterations (taking ~10 seconds), printing "Daemon thread running..." 20 times before the program ends.

Real-life use cases of daemon threads

  • Garbage Collector The JVM's own GC runs as a daemon thread; it should never prevent the JVM from shutting down.
  • Background logging Flushing logs or metrics to a file/server periodically, where losing the last few entries on shutdown is acceptable.
  • Heartbeat / keep-alive threads Sending periodic pings to a server while the application is alive.
  • Cache invalidation A background thread that evicts stale entries from an in-memory cache.
  • Auto-save Periodically saving a draft in an editor; the user closing the app shouldn't be blocked by this.

Question 3: A Shorter Way to Create Threads (Lambda)

What output do you get from the program?

Thread is running using a ...!

(Printed from the newly spawned thread.)

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

It is called a lambda expression (introduced in Java 8). It provides a concise way to implement a functional interface — an interface with exactly one abstract method. Since Runnable has only one method (run()), a lambda can be used anywhere a Runnable is expected.

How is this different from extending Thread or implementing Runnable?

Approach Code required Reusability Notes
extends Thread Full class definition Low — must subclass Thread, can't extend anything else Tightly couples logic to thread machinery
implements Runnable Full class + new Thread(r) Higher — decouples task from thread Preferred for named/reusable task classes
Lambda One-liner inline Low — anonymous, inline only Best for short, one-off tasks

The lambda approach is essentially anonymous shorthand for implements Runnable — the compiler generates an implementation of Runnable.run() under the hood. It is the most concise option but is best suited for simple, short tasks. For complex or reusable tasks, a named class implementing Runnable is clearer.

// These three are functionally equivalent:

// 1. Class extending Thread
class MyThread extends Thread {
    public void run() { System.out.println("Running"); }
}
new MyThread().start();

// 2. Anonymous Runnable
new Thread(new Runnable() {
    public void run() { System.out.println("Running"); }
}).start();

// 3. Lambda (shortest)
new Thread(() -> System.out.println("Running")).start();