143 lines
4.9 KiB
Markdown
143 lines
4.9 KiB
Markdown
|
|
# `start()` vs `run()`
|
|
|
|
## Output
|
|
|
|
The output will be similar to:
|
|
|
|
```text
|
|
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:
|
|
|
|
```text
|
|
Main thread ends.
|
|
```
|
|
|
|
Sometimes it may also print one or more lines like:
|
|
|
|
```text
|
|
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:
|
|
|
|
```java
|
|
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:
|
|
|
|
```text
|
|
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:
|
|
|
|
```text id="q7k4m3"
|
|
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:
|
|
|
|
```java id="9xw2aq"
|
|
() -> {
|
|
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:
|
|
|
|
```java id="6g5v1p"
|
|
class MyRunnable implements Runnable {
|
|
public void run() {
|
|
System.out.println("Thread running");
|
|
}
|
|
}
|
|
```
|
|
|
|
With a lambda expression, the same idea can be written directly:
|
|
|
|
```java id="v4c2km"
|
|
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.
|