Adds notes.

This commit is contained in:
Tanmay 2022-10-15 16:22:27 +01:00
parent 6271b54f12
commit 6f4cf12180
10 changed files with 129 additions and 13 deletions

14
.vscode/launch.json vendored
View File

@ -4,6 +4,13 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "Launch App",
"request": "launch",
"mainClass": "com.scaler.App",
"projectName": "os"
},
{
"name": "Python: Current File",
"type": "python",
@ -11,7 +18,12 @@
"program": "${file}",
"console": "integratedTerminal",
"justMyCode": true,
"args": ["-H", "127.0.0.1", "-p", "5001"]
"args": [
"-H",
"127.0.0.1",
"-p",
"5001"
]
}
]
}

View File

@ -1,3 +1,4 @@
{
"python.formatting.provider": "black"
"python.formatting.provider": "black",
"java.configuration.updateBuildConfiguration": "interactive"
}

View File

@ -1,23 +1,28 @@
package com.scaler;
import com.scaler.threads.Printer;
/**
* Hello world!
*
*/
public class App {
public static void print() {
System.out.println("Hello World! printed by: " + Thread.currentThread().getName());
}
public static void main(String[] args) {
print();
System.out.println("Hello world. Printed by :" + Thread.currentThread().getName());
for (int i = 0; i < 10; i++) {
TextPrinter textPrinter = new TextPrinter(String.valueOf(i));
Thread thread = new Thread(textPrinter);
Printer printer = new Printer(String.valueOf(i));
Thread thread = new Thread(printer);
thread.start();
}
}
}
// Print number 1 to 10 on a single thread
// Print number 1 to 10 each on different threads
// 1 - Thread 1
// 2 - Thread 2
// ...
// 10 Thread 10
//

View File

@ -51,3 +51,10 @@ public class FirstComeFirstServe {
return queue;
}
}
// Side-assignment
// Implement tie breaking in scheduling
// If two processes have the same arrival time
// * Check the id
// * Also, you can check the burst time
// One line code

View File

@ -8,7 +8,7 @@ import lombok.Setter;
public class IncomingProcess {
private int id;
private int arrivalTime;
private int burstTime;
private int burstTime; // How long the process will take to complete
private int completedAt;
@ -18,3 +18,5 @@ public class IncomingProcess {
this.burstTime = burstTime;
}
}
// List<ScheduleProcess> schedule(List<IncomingProcess>)

View File

@ -0,0 +1,14 @@
package com.scaler.threads;
import lombok.AllArgsConstructor;
@AllArgsConstructor
public class Printer implements Runnable {
private String text;
@Override
public void run() {
System.out.println(text + " Printed by " + Thread.currentThread().getName());
}
}

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,75 @@
# Threads and Synchronisation
## 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);
```
## Synchronisation
Whenever we have multiple threads that access the same resource, we need to make sure that the threads do not interfere with each other. This is called synchronisation.
Synchronisation can be seen in the adder and subtractor example. The adder and subtractor threads access the same counter variable. If the adder and subtractor threads do not synchronise, the counter variable can be in an inconsistent state.
* 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?