4.0 KiB
Theoretical Questions
1. start() vs run()
Question 1: What output do you get from the program? Why?
output:
Calling run()
Running in: main
Calling start()
Running in: Thread-2
Explanation:
When t1.run() is called, the run() method executes like a normal method call in the current thread, which is the main thread. Therefore, Thread.currentThread().getName() returns "main".
When t2.start() is called, Java creates a new thread named "Thread-2" and executes the run() method inside that new thread. Therefore, the output shows "Thread-2".
Question 2: What’s the difference in behavior between calling start() and run()?
| start() | run() |
|---|---|
| Creates a new thread. | Does not create a new thread. |
Executes run() concurrently. |
Executes run() in the current thread. |
| Thread scheduler manages execution. | Behaves like a normal method call. |
| Enables true multithreading. | No multithreading occurs. |
2. Daemon Threads
Question 1: What output do you get from the program? Why?
Typical output:
Main thread ends.
Or a few lines such as:
Daemon thread running...
Main thread ends.
Explanation:
The created thread is marked as a daemon thread using:
thread.setDaemon(true);
A daemon thread runs in the background and does not prevent the JVM from shutting down. Once the main thread finishes, there are no user (non-daemon) threads left, so the JVM terminates immediately. As a result, the daemon thread may not complete all 20 iterations.
Question 2: What happens if you remove thread.setDaemon(true)?
The thread becomes a normal user thread.
In that case, the JVM waits for the thread to finish before exiting. The program continues running for approximately 10 seconds (20 × 500 ms), and all 20 messages are printed.
Example output:
Main thread ends.
Daemon thread running...
Daemon thread running...
...
The program exits only after the thread completes its work.
Question 3: What are some real-life use cases of daemon threads?
Daemon threads are commonly used for background services, such as:
- Garbage collection.
- Monitoring system resources.
- Periodic cleanup tasks.
- Cache maintenance.
- Logging services.
- Background status reporting.
These tasks are supportive and should not keep the application alive when all user threads have finished.
3. A Shorter Way to Create Threads
Question 1: What output do you get from the program?
Output:
Thread is running using a ...!
The message is printed by the newly created thread after thread.start() is called.
Question 2: What is the () -> { ... } syntax called?
This syntax is called a Lambda Expression.
Lambda expressions provide a concise way to implement functional interfaces such as Runnable.
Question 3: How is this code different from creating a class that extends Thread or implements Runnable?
Extending Thread
class MyThread extends Thread {
public void run() {
System.out.println("Hello");
}
}
- Requires creating a separate class.
- Less flexible because Java does not support multiple inheritance.
Implementing Runnable
class MyRunnable implements Runnable {
public void run() {
System.out.println("Hello");
}
}
- Separates the task from the thread.
- More flexible and commonly preferred.
Using a Lambda Expression
Thread thread = new Thread(() -> {
System.out.println("Hello");
});
- Shortest and most readable approach.
- No need for an extra class.
- Ideal when the task is simple and used only once.
- Internally still provides an implementation of the
Runnableinterface.
Therefore, lambda expressions offer a concise and modern way to create threads while keeping the code easy to read and maintain.