Files
2026-06-06 00:26:13 +03:30

4.0 KiB
Raw Permalink Blame History

Assignment 8: Multithreading Basics - Theoretical Report

1. start() vs run()

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

Q1: What output do you get from the program? Why?

The output shows that t1.run() executes within the main thread, while t2.start() executes in a new, separate thread named Thread-2. This happens because run() is just a regular method call, whereas start() triggers the JVM to create a new call stack and invoke the run() method in that new thread.

Q2: Whats the difference in behavior between calling start() and run()?

The fundamental difference lies in how the JVM handles the execution. When you call t.run(), no new thread is created; instead, the method is executed synchronously within the current thread (the callers thread), much like any other normal method. This is a blocking operation.

In contrast, when you call t.start(), the JVM performs the necessary heavy lifting to create a new thread in the system. Once the new thread is allocated, the JVM invokes the run() method asynchronously in that new threads context. This allows the caller thread to continue its execution without waiting for the task to finish, enabling true concurrency.

2. Daemon Threads

Main thread ends.
Daemon thread running...

(Note: The “Daemon thread running…” messages will stop almost immediately after “Main thread ends” is printed, and might only appear once or twice before the program terminates.)

Q1: What output do you get from the program? Why?

A: The program prints “Main thread ends” and then perhaps one or two “Daemon thread running…” messages, then exits. This is because the thread is marked as a Daemon. In Java, the JVM exits as soon as all User Threads (non-daemon threads) finish their execution. Since the only user thread here is the main thread, once it finishes, the JVM shuts down regardless of whether the Daemon thread is still running.

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

A: If the line is removed, the thread becomes a User Thread. The JVM will not exit until the thread completes its entire loop (all 20 iterations). Consequently, you would see the message “Daemon thread running…” printed 20 times before the program finally terminates.

Q3: What are some real-life use cases of daemon threads?

A: Daemon threads are used for background tasks that support the main application but are not essential for the applications survival. Examples include:

Garbage Collection (GC): The JVM runs a daemon thread to manage memory in the background. Background Monitoring: Services that monitor system health or resource usage. Auto-save features: Periodically saving work in an editor without blocking the user. Cache Eviction: Periodically cleaning up expired items from a memory cache.

3. A shorter way to create threads

Thread is running using a ...!

Q1: What output do you get from the program?

A: The output is: Thread is running using a ...!.

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

A: This is called a Lambda Expression. It was introduced in Java 8 as a concise way to represent a functional interface (in this case, the Runnable interface).

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

A:

Lambda expressions significantly reduce verbosity. Instead of writing a full class definition or an anonymous inner class, you can provide the logic in a single line.

Compared to extending the Thread class, using a Lambda (which implements Runnable under the hood) is superior because it follows the principle of “composition over inheritance.” Since Java does not support multiple inheritance, implementing Runnable via a Lambda allows your class to still extend another parent class if needed.

Compared to the traditional way of implementing the Runnable interface with a formal class, the Lambda approach is much cleaner and more modern, especially for simple, stateless tasks where creating a separate file or a bulky block of code is unnecessary.