Skip to content
Open
188 changes: 177 additions & 11 deletions src/main/java/sbu/cs/MatrixMultiplication.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package sbu.cs;

import javax.swing.plaf.TableHeaderUI;
import java.beans.PropertyEditorSupport;
import java.util.ArrayList;
import java.util.List;

public class MatrixMultiplication {
Expand All @@ -8,36 +11,199 @@ public class MatrixMultiplication {
public static class BlockMultiplier implements Runnable
{
List<List<Integer>> tempMatrixProduct;
public BlockMultiplier() {
List<List<Integer>> matrix_A;
List<List<Integer>> matrix_B;
public BlockMultiplier(List<List<Integer>> matrix_A, List<List<Integer>> matrix_B) { //constructor
// TODO
this.matrix_A = matrix_A;
this.matrix_B = matrix_B;
}

@Override
public void run() {
public void run() { // the only task of threads is to multiplying those matrices
/*
TODO
Perform the calculation and store the final values in tempMatrixProduct
*/
tempMatrixProduct = multiplyingMatrix(matrix_A , matrix_B);
}
}
public List<List<Integer>> multiplyingMatrix(List<List<Integer>> matrix_A, List<List<Integer>> matrix_B) { //this method will multiply that two matrices which we pass it
int rows1 = matrix_A.size();
int cols1 = matrix_A.get(0).size();
int cols2 = matrix_B.get(0).size();

List<List<Integer>> result = new ArrayList<>();

for (int i = 0; i < rows1; i++) {
List<Integer> row = new ArrayList<>();
for (int j = 0; j < cols2; j++) {
int sum = 0;
for (int k = 0; k < cols1; k++) {
sum += matrix_A.get(i).get(k) * matrix_B.get(k).get(j);
}
row.add(sum);
}
result.add(row);
}
tempMatrixProduct = result;
return result;
}
}
// ---------------------------------- combining the four matrices(blocks) together ------------------------------------------
public List<List<Integer>> khodeMatrix (List<List<Integer>> block1 , List<List<Integer>> block2 , List<List<Integer>> block3 , List<List<Integer>> block4) {
// block 1 : up & left
// block 2 : up & right
// block 3 : down & left
// block 4 : down & right
// first we combine upper blocks then lower block with each other, then combine them to a final matrix
List<List<Integer>> finalMatrix = new ArrayList<>();
// combining block 1 & block 2 (upper blocks)
for (int i = 0 ; i < block1.size() ; i++) {
List<Integer> row = new ArrayList<>(block1.get(i));
row.addAll(block2.get(i));
finalMatrix.add(row);
}
// combining block 3 & block 4 (lower blocks)
for (int i = 0 ; i < block3.size() ; i++) {
List<Integer> row = new ArrayList<>(block3.get(i));
row.addAll(block4.get(i));
finalMatrix.add(row);
}
return finalMatrix;
}
// ---------------------------------- combining the four matrices(blocks) together ------------------------------------------
/*
Matrix A is of the form p x q
Matrix B is of the form q x r
both p and r are even numbers
*/
public static List<List<Integer>> ParallelizeMatMul(List<List<Integer>> matrix_A, List<List<Integer>> matrix_B)
{
/*
TODO
Parallelize the matrix multiplication by dividing tasks between 4 threads.
Each thread should calculate one block of the final matrix product. Each block should be a quarter of the final matrix.
Combine the 4 resulting blocks to create the final matrix product and return it.
*/
return null;
List<List<Integer>> temp1 = new ArrayList<>();
List<List<Integer>> temp2 = new ArrayList<>();
List<List<Integer>> temp3 = new ArrayList<>();
List<List<Integer>> temp4 = new ArrayList<>();

//----------------------------------------------for separating the matrix---------------------------------------------------

for (int i = 0; i < matrix_A.size()/2; i++) { // the upper part of the matrix ---> thread 1
temp1.add(matrix_A.get(i));
}

for (int i = 0; i < matrix_B.size(); i++) { // the left part of the matrix ---> thread 2
List<Integer> row = new ArrayList<>();
for (int j = 0; j < matrix_B.get(0).size()/2 ; j++) {
row.add(matrix_B.get(i).get(j));
}
temp2.add(row);
}

for (int i = matrix_A.size()/2 ; i < matrix_A.size(); i++) { // the down part of the matrix --->thread 3
temp3.add(matrix_A.get(i));
}

for (int i = 0; i < matrix_B.size(); i++) { // the right part of the matrix ---> thread 4
List<Integer> row = new ArrayList<>();
for (int j = matrix_B.get(0).size()/2 ; j < matrix_B.get(0).size() ; j++) {
row.add(matrix_B.get(i).get(j));
}
temp4.add(row);
}

// ----------------------------------------------for separating the matrix---------------------------------------------------

List<BlockMultiplier> listOfBlocks = new ArrayList<>();

BlockMultiplier blockMultiplier1 = new BlockMultiplier(temp1 , temp2); //up & left
listOfBlocks.add(blockMultiplier1);

BlockMultiplier blockMultiplier2 = new BlockMultiplier(temp1 , temp4); //up & right
listOfBlocks.add(blockMultiplier2);

BlockMultiplier blockMultiplier3 = new BlockMultiplier(temp3 , temp2); // down & left
listOfBlocks.add(blockMultiplier3);

BlockMultiplier blockMultiplier4 = new BlockMultiplier(temp3 , temp4); //down & right
listOfBlocks.add(blockMultiplier4);

// -------------------------------------------------------------------------------------------------------------------------

// ----------------------------------------------for starting the threads---------------------------------------------------

List<Thread> listOfThreads = new ArrayList<>();
for (BlockMultiplier blockMultiplier : listOfBlocks) {
Thread thread = new Thread(blockMultiplier);
listOfThreads.add(thread);
}

for (Thread listOfThread : listOfThreads) {
listOfThread.start();
}

for (Thread thread : listOfThreads) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

// ----------------------------------------------for starting the threads---------------------------------------------------
// -------------------------------------------------------------------------------------------------------------------------
// ---------------------------------- combining the four matrices(blocks) together ------------------------------------------

MatrixMultiplication matrixMultiplication = new MatrixMultiplication();

// ---------------------------------- combining the four matrices(blocks) together ------------------------------------------
// -------------------------------------------------------------------------------------------------------------------------
List<List<Integer>> matrix = matrixMultiplication.khodeMatrix(blockMultiplier1.tempMatrixProduct ,
blockMultiplier2.tempMatrixProduct , blockMultiplier3.tempMatrixProduct , blockMultiplier4.tempMatrixProduct);
return matrix;
}

public static void main(String[] args) {
// Test your code here
List<List<Integer>> matrix_A = new ArrayList<>();
List<List<Integer>> matrix_B = new ArrayList<>();
List<Integer> row1A = new ArrayList<>();
row1A.add(1);
row1A.add(2);
row1A.add(3);
List<Integer> row2A = new ArrayList<>();
row2A.add(4);
row2A.add(5);
row2A.add(6);
List<Integer> row3A = new ArrayList<>();
row3A.add(7);
row3A.add(8);
row3A.add(9);
List<Integer> row4A = new ArrayList<>();
row4A.add(10);
row4A.add(11);
row4A.add(12);
matrix_A.add(row1A);
matrix_A.add(row2A);
matrix_A.add(row3A);
matrix_A.add(row4A);
List<Integer> row1B = new ArrayList<>();
row1B.add(13);
row1B.add(14);
List<Integer> row2B = new ArrayList<>();
row2B.add(17);
row2B.add(16);
List<Integer> row3B = new ArrayList<>();
row3B.add(17);
row3B.add(18);
matrix_B.add(row1B);
matrix_B.add(row2B);
matrix_B.add(row3B);
BlockMultiplier blockMultiplier = new BlockMultiplier(matrix_A , matrix_B);
List<List<Integer>> result;
result = blockMultiplier.multiplyingMatrix(matrix_A , matrix_B);
for (List<Integer> innerList : result) {
for (Integer element : innerList) {
System.out.print(element + " ");
}
System.out.println();
}
}
}
51 changes: 44 additions & 7 deletions src/main/java/sbu/cs/TaskScheduler.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package sbu.cs;

import com.sun.source.tree.TryTree;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class TaskScheduler
Expand All @@ -9,43 +13,76 @@ public static class Task implements Runnable
{
/*
------------------------- You don't need to modify this part of the code -------------------------
*/
*/
String taskName;
int processingTime;

public Task(String taskName, int processingTime) {
this.taskName = taskName;
this.processingTime = processingTime;
}
public int getProcessingTime() {
return processingTime;
}
/*
------------------------- You don't need to modify this part of the code -------------------------
*/
*/

@Override
public void run() {

/*
TODO
Simulate utilizing CPU by sleeping the thread for the specified processingTime
*/

try{
System.out.println(taskName + " is started ");
Thread.sleep(processingTime);
}catch(Exception e) {
System.out.println(e.getMessage());
}
}
}

public static ArrayList<String> doTasks(ArrayList<Task> tasks)
{
public static ArrayList<String> doTasks(ArrayList<Task> tasks) throws InterruptedException {
ArrayList<String> finishedTasks = new ArrayList<>();

Collections.sort(tasks , Comparator.comparing(Task::getProcessingTime)); // for sorting the objects base on their processing time
/*
TODO
Create a thread for each given task, And then start them based on which task has the highest priority
(highest priority belongs to the tasks that take more time to be completed).
You have to wait for each task to get done and then start the next task.
Don't forget to add each task's name to the finishedTasks after it's completely finished.
*/

Thread thread;
for (int i = 0 ; i < tasks.size() ; i++) {
thread = new Thread(tasks.get(i));
thread.start();
try {
thread.join();
}catch (Exception e){
e.printStackTrace();
}
}
for (int i = tasks.size()-1 ; i >= 0 ; i--) { // coping the tasks array list in the finishedTasks array list
finishedTasks.add(tasks.get(i).taskName);
}
return finishedTasks;
}

public static void main(String[] args) {
public static void main(String[] args) throws InterruptedException {
// Test your code here
ArrayList<Task> tasks = new ArrayList<>();

tasks.add(new Task("A", 1000));
tasks.add(new Task("B", 1200));
tasks.add(new Task("C", 5000));
tasks.add(new Task("E", 2000));
tasks.add(new Task("F", 3000));

// for (int i = 0 ; i < tasks.size() ; i++ ) {
System.out.println(doTasks(tasks));
// }
}
}
76 changes: 76 additions & 0 deletions src/main/java/sbu/cs/Theory-Questions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
### First Code :
```

public static class SleepThread extends Thread {
public void run() {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
System.out.println("Thread was interrupted!");
} finally {
System.out.println("Thread will be finished here!!!");
}
}
}

public static void main(String[] args) {
SleepThread thread = new SleepThread();
thread.start();
thread.interrupt();
}

```
### Output :
#### "Thread was interrupted!"
#### "Thread will be finished here!!!"


### Why :
#### in this provided code inside the main method we call the start method to start the threads, so it means the thread is trying to be run then we call the interrupt() method which will interrupt the function of the thread and it makes an exception, why ? because the thread is running then we interrupt its function so the output will be : "Thread was interrupted!" and then "Thread will be finished here!!!".
### Second Code :
```
public class DirectRunnable implements Runnable {
public void run() {
System.out.println("Running in: " + Thread.currentThread().getName());
}
}

public class Main {
public static void main(String[] args) {
DirectRunnable runnable = new DirectRunnable();
runnable.run();
}
}
```

### Output :
#### Running in: main
### Why :
#### when we do not initialize a new Thread it will consider the default thread means main thread then the current thread will be main thread
### Third Code :
```
public class JoinThread extends Thread {
public void run() {
System.out.println("Running in: " + Thread.currentThread().getName());
}
}

public class Main {
public static void main(String[] args) {
JoinThread thread = new JoinThread();
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Back to: " + Thread.currentThread().getName());
}
}
```
### Answer :
#### because the join() method causes this event : the calling thread to wait for the specified thread to be finished :
#### 1. we are taking an object from that class which will run the thread
#### 2. we call start() method for that thread
#### 3. then we are calling the join() method for that thread which is meaning this that the calling thread will wait for the specific thread to be ran and executed then it will continue which in this code the Mian thread will wait for the object thread to be executed then the Main thread will continue****