# The Threads

### The Main Thread

Every process has at least one thread called the main thread. Java provides us with the `Threads` class to interact with threads. To get the current thread we can use a static method defined in the `Thread` class called the `.currentThread()`  
To prove that all programs contain a main thread let's take a simple Java program as an example:

```java
public class Main {
    public static void main(String[] args) {
        System.out.println("Hello World");
        System.out.println(Thread.currentThread());
    }
}

// -- output
Hello World
Thread[main,5,main]
```

The current thread object in the above program has been printed on the terminal. The output `Thread[main,5,main]` states that the current thread name is `main`, the priority of the main thread is 5 and the name of the thread group where the main thread resides is also `main`. We have discussed priorities in the [Introduction to Multithreading](https://blog.rizwan.io/introduction-to-multithreading) article.

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">A thread group is a collection of threads, with the help of thread groups we can perform operations on multiple threads collectively.</div>
</div>

### Controlling the \[Main\] Thread - Name & Priority.

We can control and configure any thread, but since we just only learned about the main thread, let us try to configure it. We can change the name of the thread using the `.setName(String name)` method and priority using the `.setPriority(int priority)` method. A name can be any name of our choice. A priority of the thread can be between 1 and 10, 1 being the lowest and 10 being the highest. We can also use constants defined in the `Thread` class to set the priority i.e. `Thread.MIN_PRIORITY`, `Thread.MAX_PRIORITY`, `Thread.NORM_PRIORITY`. The `MIN_PRIORITY` has the value 1, `MAX_PRIORITY` has the value 10 and `NORM_PRIORITY` has the value 5. If priority is not provided then five is the default priority.

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Note: <code>Thread.currentThread()</code> returns the object of type <code>Thread</code></div>
</div>

The `.setName(String name)` and `.setPriority(int priority)` are not static methods but rather instance methods defined on the thread object. Similar to the set, we can also get these properties using `.getName()` and `.getPriority()` method.

```java
public static void main(String[] args) {
    Thread currentThread = Thread.currentThread();
    System.out.println("Thread name before: " + currentThread.getName());
    System.out.println("Thread priority before: " + currentThread.getPriority());

    currentThread.setName("The Main Main Thread");
    currentThread.setPriority(10);

    System.out.println();
    System.out.println("Thread name after: " + currentThread.getName());
    System.out.println("Thread priority after: " + currentThread.getPriority());
}

// --output
Thread name before: main
Thread priority before: 5

Thread name after: The Main Main Thread
Thread priority after: 10
```

### Thread creation

We already know that Java provides us with the `Thread` class to deal with threads. Hence to create threads in Java, we have to create an object of the `Thread` class. We can create a thread object using two ways:

1. Approach One - `extends Thread`
    

Since inheritance represents an IS-A relationship. Hence, we can use inheritance to create a custom thread class.

```java
public class MyCustomThread extends Thread { }
```

Only creating a custom thread class is of no use. To make use of this class we have to override the `run` method in this class. *The* `run()` *method serves as the entry point of the thread execution.*

```java
public class MyCustomThread extends Thread {
    @Override
    public void run() {
        System.out.println("Hello from " + Thread.currentThread().getName());
    }
}
```

After class creation, we have to instantiate the `MyCustomThread` class and **start it**. *The* `start()` *method on the thread object is used to start the thread.*

```java
public class Main {
    public static void main(String[] args) {
        MyCustomThread myCustomThread = new MyCustomThread(); // thread creation
        myCustomThread.start();                               // thread execution 
    }
}

// -- output
Hello from Thread-0
```

As we can see from the above output the name of the custom thread is `Thread-0`. We can change this name using the `setName(String name)` method. Note that you have to set the name of the thread before you start the thread.

```java
myCustomThread.setName("My Custom Thread");                         // set name

// -- output of the same program after addition of the above line before 
// -- starting the thread
Hello from My Custom Thread
```

2. Approach Two - `implements Runnable`
    

Another way to create a thread is by using its constructor, There are many forms of its constructor the one which is used popularly is the `new Thread (Runnable object)`. It accepts an object that implements the Runnable interface. The Runnable is an interface with only one abstract method i.e. `run()`. The `run()` method is where we can write the execution logic for the thread. We can provide an object which implements the Runnable interface in any of the 3 ways:  
either by creating a class and making it implement the Runnable interface; or by using an anonymous inner class or by using Lambda expression, as Runnable is a functional interface. For the sake of simplicity, we will be using lambda expression.

```java

public class Main {
    public static void main(String[] args) {
        Thread myAnotherCustomThread = new Thread(() -> {
            System.out.println("Hello from " + 
                    Thread.currentThread().getName());
        });
        myAnotherCustomThread.start();
    }
}

// -- output
Hello from Thread-0
```

We can use another form of the constructor to directly provide a name to the thread.

```java
Thread myAnotherCustomThread = new Thread(() -> {
            System.out.println("Hello from " +
                    Thread.currentThread().getName());
        }, "My Another Custom Thread");
        myAnotherCustomThread.start();
```

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Since there are 2 ways to create a thread, which one should you choose? It comes down to personal preference, but as a general rule of thumb, you should use <code>extends Thread</code> if you intend to override other methods of the thread as well.</div>
</div>

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Capable vs Enhanced -- When you make a class extend to a base class you are creating an enhanced version of the base class, If you create a class that implements an interface then you are creating a class which is capable of being the instance of the interface.</div>
</div>

### Creating Multiple Threads

We can also create multiple threads and start them all together. For example, in the below code, we are creating a thread in the `for loop` and adding it to a `list of threads`. After all the `threads` have been added we are again iterating over the `list` and starting all the `threads` one by one.

```java
public class Main {
    public static void main(String[] args) {
        List<Thread> threads = new ArrayList<>();

        for (int i = 0; i < 4; i++) {
            Thread thread = new Thread(() -> {
                System.out.println("Hello from: " + 
                                    Thread.currentThread().getName());
            });
            threads.add(thread);
        }

        for (Thread thread : threads) thread.start();
    }
}

// -- output (order of the output may differ)
Hello from: Thread-0
Hello from: Thread-3
Hello from: Thread-1
Hello from: Thread-2
```

### The `sleep()` method

Remember that OS schedules different threads so that they receive a chunk of CPU resources and get executed? The `sleep()` method is a static method declared in the `Thread` class that makes the thread sleep for the specified time which is generally in milliseconds. Behind the scenes, it makes the CPU not schedule the thread until the specified time has elapsed. This method throws an `InterruptedException`, which should be handled. This exception is thrown when any other thread sends an `interrupt` signal to the thread while it is sleeping.

In the below code, we are simulating a process of downloading 4 files using the sleep method.

```java
    public static void main(String[] args) {
        List<Thread> threads = new ArrayList<>();

        for (int i = 0; i < 4; i++) {
            Thread thread = new Thread(() -> {
                try {
                    // wait for 1 second before proceeding further
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("Hello from: " + 
                                    Thread.currentThread().getName());
            });
            threads.add(thread);
        }

        for (Thread thread : threads) thread.start();
    }

// -- output, after waiting 1 second. The output of the order may change. 
Hello from: Thread-2
Hello from: Thread-0
Hello from: Thread-3
Hello from: Thread-1
```

On executing the above code, we get the mentioned output after waiting for approx 1 second. Note that all the lines of the output may be printed together (if your machine has 4 or more cores). To check the number of cores in your machine we can use the below code:

```java
int numberOfCores = Runtime.getRuntime().availableProcessors();
System.out.println("Total no. of available cores are " + numberOfCores);

// -- output
Total no. of available cores are 8
```

Since I have 8 cores available in my machine that means I can run 8 threads in parallel (In ideal conditions).

### The `isAlive()` & `join()` method

Threads run independently from each other and the order of their execution is out of our control. What would happen if one thread is dependent on the result of the other thread for its execution? One solution for this problem is busy waiting. In which `thread A` which depends on the other `thread B` for its execution, runs an empty `while` loop to check if `thread B` has been completed its execution. To do this we can use the `isAlive()` method defined on the thread object. Tho this seems like a complete waste of resources still, we should explore its working.

Let's take a scenario, where we are downloading a file and then scanning it for viruses. For simplicity, we will be printing a log statement instead of downloading a file and scanning it.

```java
public class Main {
    public static void main(String[] args) {
        Thread downloadThread = new Thread(() -> {
            // logic for downloading the file
            System.out.println("Downloading File");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("Download Complete");
        });

        Thread scanThread = new Thread(() -> {
            // logic for scanning the file
            System.out.println("Scanning File");
            System.out.println("Scan Complete");
        });

        downloadThread.start();
        scanThread.start();
    }
}

// -- output
Downloading File
Scanning File
Scan Complete
Download Complete
```

As we can see the above code has started the scanning process and also completed it before the file can be downloaded. This is not the expected behaviour. We can use busy-wait to continuously check if the `downloadThread` is still alive before starting the `scanThread`.

```java

downloadThread.start();

// an empty while loop to only check if the downloadThread has been terminated
// -- busy-wait
while (downloadThread.isAlive());
scanThread.start();

// -- output
Downloading File
Download Complete
Scanning File
Scan Complete
```

There can be many other scenarios where the `isAlive()` method is of great use but this is not one of those scenarios. Using busy-wait here is a complete waste of resources.

The desired solution is that the dependent thread should go to sleep until the other thread has completed its execution and only after that it should wake up. We can achieve this by using the `join()` method declared on the thread object. The `join()` method waits until the thread on which it is called terminates. *Its name comes from the concept of the calling thread waiting until the specified thread joins it*. Let's take the same example as above that gives the following unexpected output.

```java
// --output
Downloading File
Scanning File
Scan Complete
Download Complete
```

To solve this problem in an efficient way we can use the `join()` method. We can call the `join` method on the `downloadThread` thread, after starting the `downloadThread` but before starting the `scanThread`.

```java
downloadThread.start();
try {
    downloadThread.join();
     // -- the main thread waits here until the download thread is complete
} catch (InterruptedException e) {
    throw new RuntimeException(e);
}

scanThread.start();

// --output
Downloading File
Download Complete
Scanning File
Scan Complete
```

Note: Since the `join()` method makes the calling thread go to sleep, hence the `join()` method also throws an `InterruptedException` that needs to be handled.

As a good practice, we should use another version of the `join()` method that waits for the specified time before it can proceed further irrespective of the completion of the thread.

```java
downloadThread.join(2000);
```

### The Daemon threads

By default, the application will not stop until we have at least one thread running in it. Daemon threads are the threads that don’t prevent the application from exiting even if the main thread terminates. For example: any background thread that should not block our application from terminating. To mark a thread as a daemon thread we can use the `setDaemon` property:

```java

public class Main {
    public static void main(String[] args) {
        Thread downloadThread = new Thread(() -> {
            // logic for downloading the file
            System.out.println("Downloading File");
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("Download Complete");
        });

        downloadThread.setDaemon(true);
        downloadThread.start();
    }
}
```

### Thread Interruption

There are many cases in which we might have to terminate a thread or break out of the sleeping state of the threat or if the thread is misbehaving.

**Interrupt Signal**

We can terminate a thread by sending an *interrupt* signal to it i.e. By setting the interrupt flag of the thread to true. We can do this by using the interrupt method which is declared on the thread object. Note that just sending the interrupt signal is not enough it is solely on the thread on how it chooses to behave when an interrupt signal is received.

Hence, it makes sense to send an interrupt signal only in the following 2 cases:

1. When a thread is executing a method that can throw an interruptedException on being interrupted. For example `thread.sleep()`
    

```java
public class Main {
    public static void main(String[] args) {
        Thread downloadThread = new Thread(() -> {
            // logic for downloading the file
            System.out.println("Downloading File");
            // interrupt signal is being handled if the thread is asleep
            try {
                // waiting 10 secs before completing the thread
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("Download Complete");
        });

        downloadThread.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        // sending interrupt signal after waiting for a second
        downloadThread.interrupt();
    }
}

// -- output
Downloading File
Exception in thread "Thread-0" java.lang.RuntimeException: java.lang.InterruptedException: sleep interrupted
	at io.rizwan.Main.lambda$main$0(Main.java:13)
	at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.InterruptedException: sleep interrupted
	at java.base/java.lang.Thread.sleep(Native Method)
	at io.rizwan.Main.lambda$main$0(Main.java:11)
	... 1 more
```

2. If the interrupt signal is explicitly handled. To demonstrate this let's take a computation task that takes a long time to complete, Calculating an exponential power of a number. To explicitly check if the current thread is interrupted we can call the static method called `Thread.interrupted()` declared the Thread class.
    

```java
import java.math.BigInteger;

public class Main {
    public static void main(String[] args) {
        BigInteger base = BigInteger.valueOf(200000);
        BigInteger power = BigInteger.valueOf(100000);

        Thread longComputationThread = new Thread(() -> {
            System.out.println(base + "^" + power + " = " + pow(base, power));
        });

        longComputationThread.start();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        longComputationThread.interrupt();
    }

    public static BigInteger pow(BigInteger base, BigInteger power) {
        BigInteger result = BigInteger.ONE;

        for (BigInteger i = BigInteger.ZERO; 
                    i.compareTo(power) != 0; 
                    i = i.add(BigInteger.ONE)) {
            // checking continuously is the thread is interrupted
            if (Thread.interrupted()) {
                System.out.println("Prematurely interrupted computation");
                return BigInteger.ZERO;
            }
            result = result.multiply(base);
        }

        return result;
    }
}

// -- output
Prematurely interrupted computation
200000^100000 = 0
```

In the above code instead of using `Thread.interrupted()` to check if the current thread is interrupted, we can also use `Thread.currentThread().isInterrupted()`. The only difference between these 2 methods is that:

The `Thread.interrupted()` method will change the status of the interrupt flag to false after returning it. So if the thread is interrupted and there are 2 calls to the `Thread.interrupted()` method then the first call will return true whereas the second will return false.

The `Thread.currentThread().isInterrupted()` will only return the status of the interrupt flag.

### What's Next?

When we solve one problem, we create another. In the next post, we will be exploring what problem we have created by using multithreading.

---

**References:**

1. [**Java Multithreading, Concurrency & Performance Optimization**](https://www.udemy.com/course/java-multithreading-concurrency-performance-optimization/?couponCode=LEARNNOWPLANS)
    
2. [**JAVA THE COMPLETE REFERENCE, 13E**](https://amzn.in/d/ds6NgFq)
    
3. [Ultimate Java Part 3: Advanced Topics](https://codewithmosh.com/p/ultimate-java-part-3)
