mirror of
https://github.com/robindhole/fundamentals.git
synced 2025-03-15 21:50:16 +00:00
Adds consolidated threads notes.
This commit is contained in:
parent
a0c5f8a633
commit
05cb2d1fb9
200
os/notes/threads-consolidated.md
Normal file
200
os/notes/threads-consolidated.md
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
# Threads and Multithreading
|
||||||
|
|
||||||
|
## Threads
|
||||||
|
|
||||||
|
> A thread is a lightweight process. It is a unit of execution within a process. A process can have multiple threads. Each thread has its own program counter, stack, and registers. Threads share the same address space. This means that all threads in a process can access the same memory. This is different from processes where each process has its own address space.
|
||||||
|
|
||||||
|
Often, a process needs to perform multiple tasks at the same time. For example, a web browser needs to download a file and display a web page at the same time. Creating a new process for each task is expensive. This is because creating a new process requires a lot of resources.
|
||||||
|
|
||||||
|
Threads are used to solve this problem. Threads are used to perform multiple tasks within a process. This is done by sharing the same address space. This means that all threads in a process can access the same memory. This is different from processes where each process has its own address space.
|
||||||
|
|
||||||
|
Thread is a sequential flow of tasks within a process. Threads in OS can be of the same or different types. Threads are used to increase the performance of the applications.
|
||||||
|
Each thread has its own program counter, stack, and set of registers. But the threads of a single process might share the same code and data/file. Threads are also termed as lightweight processes as they share common resources.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
### Thread vs Process
|
||||||
|
| Process | Thread |
|
||||||
|
| -------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
|
||||||
|
| Processes use more resources and hence they are termed as heavyweight processes. | Threads share resources and hence they are termed as lightweight processes. |
|
||||||
|
| Creation and termination times of processes are slower. | Creation and termination times of threads are faster compared to processes. |
|
||||||
|
| Processes have their own code and data/file. | Threads share code and data/file within a process. |
|
||||||
|
| Communication between processes is slower. | Communication between threads is faster. |
|
||||||
|
| Context Switching in processes is slower. | Context switching in threads is faster. |
|
||||||
|
| Processes are independent of each other. | Threads, on the other hand, are interdependent. (i.e they can read, write or change another thread’s data) |
|
||||||
|
| Eg: Opening two different browsers. | Eg: Opening two tabs in the same browser. |
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Concurrency vs Parallelism
|
||||||
|
|
||||||
|
* Concurrent - At the same time, but not necessarily at the same instant. It is possible for multiple threads to be at different stages of execution at the same time but not being processed together. A single core CPU can only execute one thread at a time. But it can switch between threads very quickly. This is called context switching. This is how concurrency is achieved. A single core CPU can have concurrency but not parallelism.
|
||||||
|
* Parallel - At the same time and at the same instant. It is possible for multiple threads to be at different stages of execution at the same time and being processed together. A single core CPU cannot achieve parallelism. It can only achieve concurrency. A multi-core CPU can achieve both concurrency and parallelism.
|
||||||
|
|
||||||
|
|
||||||
|
### Using threads in Java
|
||||||
|
|
||||||
|
|
||||||
|
In Java, we can create a thread by extending the Thread class or by implementing the Runnable interface. The Thread class is a subclass of the Object class. It implements the Runnable interface. The Runnable interface has a single method called run(). This method is called when the thread is started.
|
||||||
|
|
||||||
|
```java
|
||||||
|
class NewThread implements Runnable {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// Code to be executed by the thread
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
We can create a new thread by creating an object of the NewThread class and passing it to the Thread class constructor. The Thread class constructor takes a Runnable object as an argument. This Runnable object is the thread that we want to create.
|
||||||
|
|
||||||
|
```java
|
||||||
|
NewThread newThread = new NewThread();
|
||||||
|
Thread thread = new Thread(newThread);
|
||||||
|
```
|
||||||
|
|
||||||
|
To run the thread, we call the start() method on the Thread object. This method calls the run() method of the Runnable object. The run() method is executed by the thread.
|
||||||
|
|
||||||
|
```java
|
||||||
|
thread.start();
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Number printer
|
||||||
|
|
||||||
|
**Problem Statement**
|
||||||
|
* Create a new thread that prints the numbers from 1 to 10.
|
||||||
|
|
||||||
|
**Solution**
|
||||||
|
```java
|
||||||
|
class NumberPrinter implements Runnable {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
for (int i = 1; i <= 10; i++) {
|
||||||
|
System.out.println(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class Main {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
NumberPrinter numberPrinter = new NumberPrinter();
|
||||||
|
Thread thread = new Thread(numberPrinter);
|
||||||
|
thread.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Problem Statement 2**
|
||||||
|
* Print the numbers from 1 to 10 where each number is printed by a different thread.
|
||||||
|
|
||||||
|
***Solution***
|
||||||
|
```java
|
||||||
|
class NumberPrinter implements Runnable {
|
||||||
|
private int number;
|
||||||
|
|
||||||
|
public NumberPrinter(int number) {
|
||||||
|
this.number = number;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
System.out.println(number);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class Main {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
for (int i = 1; i <= 10; i++) {
|
||||||
|
NumberPrinter numberPrinter = new NumberPrinter(i);
|
||||||
|
Thread thread = new Thread(numberPrinter);
|
||||||
|
thread.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Executor
|
||||||
|
|
||||||
|
The `Executor` interface is used to execute tasks. It is a generic interface that can be used to execute any kind of task. The `Executor` interface has only one method:
|
||||||
|
|
||||||
|
```java
|
||||||
|
public interface Executor {
|
||||||
|
void execute(Runnable command);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `execute` method takes a `Runnable` object as a parameter. The `Runnable` interface is a functional interface that has only one method. Executors internally use a thread pool to execute the tasks. The `execute` method is non-blocking. It returns immediately after submitting the task to the thread pool. The `execute` method is used to execute tasks that do not return a result.
|
||||||
|
|
||||||
|
A thread pool is a collection of threads that are used to execute tasks.
|
||||||
|
Instead of creating a new thread for each task, a thread pool reuses the existing threads to execute the tasks. This improves the performance of the application.
|
||||||
|
|
||||||
|
The `Executor` interface has a method called `newCachedThreadPool` that returns an `ExecutorService` object. The `ExecutorService` interface extends the `Executor` interface. The `ExecutorService` interface has methods to execute tasks that return a result. The `ExecutorService` interface also has methods to shutdown the thread pool.
|
||||||
|
|
||||||
|
To run a task using the `Executor` interface, we can use the `newCachedThreadPool` method to create an `ExecutorService` object. The `newCachedThreadPool` method returns an `ExecutorService` object that uses a thread pool with a variable number of threads. The `newCachedThreadPool` method creates a new thread for each task if there are no idle threads in the thread pool. If there is an idle thread in the thread pool, the `newCachedThreadPool` method reuses the idle thread to execute the task. The `newCachedThreadPool` method returns an `ExecutorService` object that uses a thread pool with a variable number of threads.
|
||||||
|
|
||||||
|
```java
|
||||||
|
Executor executorService = Executors.newCachedThreadPool();
|
||||||
|
executorService.execute(() -> System.out.println("Hello World"));
|
||||||
|
```
|
||||||
|
|
||||||
|
## Callable and Future
|
||||||
|
|
||||||
|
Runnables do not return a result. If we want to execute a task that returns a result, we can use the `Callable` interface. The `Callable` interface is a functional interface that has only one method:
|
||||||
|
|
||||||
|
```java
|
||||||
|
public interface Callable<V> {
|
||||||
|
V call() throws Exception;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `call` method returns a result of type `V`. The `call` method can throw an exception. The `Callable` interface is used to execute tasks that return a result.
|
||||||
|
For instance we can use the `Callable` interface to execute a task that returns the sum of two numbers:
|
||||||
|
|
||||||
|
```java
|
||||||
|
Callable<Integer> sumTask = () -> 2 + 3;
|
||||||
|
```
|
||||||
|
|
||||||
|
In order to execute a task that returns a result, we can use the `submit` method of the `ExecutorService` interface. The `submit` method takes a `Callable` object as a parameter. The `submit` method returns a `Future` object. The `Future` interface has a method called `get` that returns the result of the task. The `get` method is a blocking method. It waits until the task is completed and then returns the result of the task.
|
||||||
|
|
||||||
|
```java
|
||||||
|
ExecutorService executorService = Executors.newCachedThreadPool();
|
||||||
|
Future<Integer> future = executorService.submit(() -> 2 + 3);
|
||||||
|
Integer result = future.get();
|
||||||
|
```
|
||||||
|
|
||||||
|
Futures can be used to cancel tasks. The `Future` interface has a method called `cancel` that can be used to cancel a task. The `cancel` method takes a boolean parameter. If the boolean parameter is `true`, the task is cancelled even if the task is already running. If the boolean parameter is `false`, the task is cancelled only if the task is not running.
|
||||||
|
|
||||||
|
```java
|
||||||
|
ExecutorService executorService = Executors.newCachedThreadPool();
|
||||||
|
Future<Integer> future = executorService.submit(() -> 2 + 3);
|
||||||
|
future.cancel(false);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Assignment
|
||||||
|
* Create a count class that has a count variable.
|
||||||
|
* Create two different classes `Adder` and `Subtractor`.
|
||||||
|
* Accept a count object in the constructor of both the classes.
|
||||||
|
* In `Adder`, iterate from 1 to 100 and increment the count variable by 1 on each iteration.
|
||||||
|
* In `Subtractor`, iterate from 1 to 100 and decrement the count variable by 1 on each iteration.
|
||||||
|
* Print the final value of the count variable.
|
||||||
|
* What would the ideal value of the count variable be?
|
||||||
|
* What is the actual value of the count variable?
|
||||||
|
* Try to add some delay in the `Adder` and `Subtractor` classes using inspiration from the code below. What is the value of the count variable now?
|
||||||
|
|
||||||
|
```java
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Reading List
|
||||||
|
|
||||||
|
* [Web Browser architecture](https://levelup.gitconnected.com/how-web-browsers-use-processes-and-threads-9f8f8fa23371)
|
Loading…
x
Reference in New Issue
Block a user