diff --git a/chapter_3/lecture_3/src/main/java/Main.java b/chapter_3/lecture_3/src/main/java/Main.java deleted file mode 100644 index 46bb1e1..0000000 --- a/chapter_3/lecture_3/src/main/java/Main.java +++ /dev/null @@ -1,38 +0,0 @@ -public class Main { - public static void main(String[] args) throws InterruptedException { - ThreadGroup group1 = new ThreadGroup("Group1"); - group1.setMaxPriority(7); - - ThreadGroup parent = group1.getParent(); - System.out.println("Parent name: " + parent.getName() + " priority = " + parent.getMaxPriority()); - - Thread thread1 = new Thread(group1, new MyThread(), "Thread1"); - Thread thread2 = new Thread(group1, new MyThread(), "Thread2"); - Thread thread3 = new Thread(group1, new MyThread(), "Thread3"); - - thread1.setPriority(Thread.MAX_PRIORITY); - - thread1.start(); - thread2.start(); - thread3.start(); - - System.out.println("Sleeping for 3 seconds..."); - Thread.sleep(3000); - - group1.interrupt(); - } - - static class MyThread implements Runnable { - @Override - public void run() { - while(true) { - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - Thread currentThread = Thread.currentThread(); - System.out.println("Name: " + currentThread.getName() + " priority = " + currentThread.getPriority()); - } - } - } - } -} diff --git a/chapter_3/lecture_7/src/main/java/Main.java b/chapter_3/lecture_7/src/main/java/Main.java deleted file mode 100644 index 8e99313..0000000 --- a/chapter_3/lecture_7/src/main/java/Main.java +++ /dev/null @@ -1,124 +0,0 @@ -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Arrays; - -/** - * === REQUIREMENTS === - * 1. Periodically scans the ./src/main/resources directory and watches for new files - * 2. For each file found into this directory, a new thread should take care of its processing - * 3. Processing = each line of the file will be hashed using a hashing algorithm - * 4. The program will create new files, marked _output suffix, and they will placed into ./src/main/output - * 5. Throw an exception if a line is empty - */ - -public class Main { - public static void main(String[] args) { - new Thread(new Watcher()).start(); - } -} - -class ExceptionHandler implements Thread.UncaughtExceptionHandler { - - @Override - public void uncaughtException(Thread t, Throwable e) { - System.out.println("Exception handled: " + e.getMessage()); - } -} - -class Watcher implements Runnable { - - @Override - public void run() { - File inputDirectory = new File("./src/main/resources"); - - while (true) { - if (inputDirectory.listFiles().length != 0) { - Arrays.stream(inputDirectory.listFiles()).forEach( - file -> { - Thread t = new Thread(new FileProcessor(file)); - t.setUncaughtExceptionHandler(new ExceptionHandler()); - t.start(); - } - ); - } - - sleep(); - } - } - - private void sleep() { - try { - Thread.sleep(60000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } -} - -class FileProcessor implements Runnable { - - private final File file; - private final static String OUTPUT_PATH = "./src/main/output/"; - - public FileProcessor(File file) { - this.file = file; - } - - @Override - public void run() { - try { - BufferedWriter writer = new BufferedWriter(new FileWriter(OUTPUT_PATH + file.getName())); - - Files.lines(Path.of(file.getCanonicalPath())) - .map(this::hash) - .map(line -> line + "\n") - .forEach(el -> { - try { - writer.write(el); - } catch (IOException e) { - e.printStackTrace(); - } - }); - - writer.close(); - - } catch (IOException e) { - e.printStackTrace(); - } - System.out.println(Thread.currentThread().getName() + " -> processed file: " + file.getName()); - } - - private String hash(String input) { - if (input.equals("")) { - throw new RuntimeException("The line is empty, hashing cannot be done"); - } - - try { - final MessageDigest digest = MessageDigest.getInstance("SHA3-256"); - final byte[] hashbytes = digest.digest(input.getBytes(StandardCharsets.UTF_8)); - return bytesToHex(hashbytes); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - return ""; - } - } - - private static String bytesToHex(byte[] hash) { - StringBuilder hexString = new StringBuilder(2 * hash.length); - for (int i = 0; i < hash.length; i++) { - String hex = Integer.toHexString(0xff & hash[i]); - if(hex.length() == 1) { - hexString.append('0'); - } - hexString.append(hex); - } - return hexString.toString(); - } -} \ No newline at end of file diff --git a/chapter_3/lecture_1/build.gradle b/chapter_3_thread_management/lecture_1_thread_creation/build.gradle similarity index 100% rename from chapter_3/lecture_1/build.gradle rename to chapter_3_thread_management/lecture_1_thread_creation/build.gradle diff --git a/chapter_3/lecture_1/gradle/wrapper/gradle-wrapper.jar b/chapter_3_thread_management/lecture_1_thread_creation/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_3/lecture_1/gradle/wrapper/gradle-wrapper.jar rename to chapter_3_thread_management/lecture_1_thread_creation/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_3/lecture_1/gradle/wrapper/gradle-wrapper.properties b/chapter_3_thread_management/lecture_1_thread_creation/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_3/lecture_1/gradle/wrapper/gradle-wrapper.properties rename to chapter_3_thread_management/lecture_1_thread_creation/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_3/lecture_1/gradlew b/chapter_3_thread_management/lecture_1_thread_creation/gradlew similarity index 100% rename from chapter_3/lecture_1/gradlew rename to chapter_3_thread_management/lecture_1_thread_creation/gradlew diff --git a/chapter_3/lecture_1/gradlew.bat b/chapter_3_thread_management/lecture_1_thread_creation/gradlew.bat similarity index 100% rename from chapter_3/lecture_1/gradlew.bat rename to chapter_3_thread_management/lecture_1_thread_creation/gradlew.bat diff --git a/chapter_3/lecture_1/settings.gradle b/chapter_3_thread_management/lecture_1_thread_creation/settings.gradle similarity index 100% rename from chapter_3/lecture_1/settings.gradle rename to chapter_3_thread_management/lecture_1_thread_creation/settings.gradle diff --git a/chapter_3/lecture_1/src/main/java/Main.java b/chapter_3_thread_management/lecture_1_thread_creation/src/main/java/Main.java similarity index 72% rename from chapter_3/lecture_1/src/main/java/Main.java rename to chapter_3_thread_management/lecture_1_thread_creation/src/main/java/Main.java index 3d5fb6f..0c5c40a 100644 --- a/chapter_3/lecture_1/src/main/java/Main.java +++ b/chapter_3_thread_management/lecture_1_thread_creation/src/main/java/Main.java @@ -1,3 +1,5 @@ +//Chapter 3 Lecture 1: Thread Creation + public class Main { // public static void main(String[] args) throws InterruptedException { // Thread thread = Thread.currentThread(); @@ -8,12 +10,11 @@ public class Main { // System.out.println("Current thread: " + thread.getName()); // } -// public static void main(String[] args) { +// public static void main(String[] args) throws InterruptedException { // // 1. Extend the Thread class -// // 2. Use Runnable interface -// +// // 2. Use runnable interface // MyThread myThread = new MyThread(); -// myThread.run(); +// myThread.start(); // } // // static class MyThread extends Thread { @@ -25,11 +26,9 @@ public class Main { public static void main(String[] args) throws InterruptedException { System.out.println("[1] Current thread: " + Thread.currentThread().getName()); - +// Runnable runnable = () -> System.out.println("Current thread: " + Thread.currentThread().getName()); Thread thread = new Thread( - () -> { - System.out.println("[2] Current thread: " + Thread.currentThread().getName()); - } + () -> System.out.println("[2] Current thread: " + Thread.currentThread().getName()) ); thread.setName("MyThread"); thread.start(); diff --git a/chapter_3/lecture_2/build.gradle b/chapter_3_thread_management/lecture_2_thread_priorities_and_state/build.gradle similarity index 100% rename from chapter_3/lecture_2/build.gradle rename to chapter_3_thread_management/lecture_2_thread_priorities_and_state/build.gradle diff --git a/chapter_3/lecture_2/gradle/wrapper/gradle-wrapper.jar b/chapter_3_thread_management/lecture_2_thread_priorities_and_state/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_3/lecture_2/gradle/wrapper/gradle-wrapper.jar rename to chapter_3_thread_management/lecture_2_thread_priorities_and_state/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_3/lecture_2/gradle/wrapper/gradle-wrapper.properties b/chapter_3_thread_management/lecture_2_thread_priorities_and_state/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_3/lecture_2/gradle/wrapper/gradle-wrapper.properties rename to chapter_3_thread_management/lecture_2_thread_priorities_and_state/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_3/lecture_2/gradlew b/chapter_3_thread_management/lecture_2_thread_priorities_and_state/gradlew similarity index 100% rename from chapter_3/lecture_2/gradlew rename to chapter_3_thread_management/lecture_2_thread_priorities_and_state/gradlew diff --git a/chapter_3/lecture_2/gradlew.bat b/chapter_3_thread_management/lecture_2_thread_priorities_and_state/gradlew.bat similarity index 100% rename from chapter_3/lecture_2/gradlew.bat rename to chapter_3_thread_management/lecture_2_thread_priorities_and_state/gradlew.bat diff --git a/chapter_3/lecture_2/settings.gradle b/chapter_3_thread_management/lecture_2_thread_priorities_and_state/settings.gradle similarity index 100% rename from chapter_3/lecture_2/settings.gradle rename to chapter_3_thread_management/lecture_2_thread_priorities_and_state/settings.gradle diff --git a/chapter_3/lecture_2/src/main/java/Main.java b/chapter_3_thread_management/lecture_2_thread_priorities_and_state/src/main/java/Main.java similarity index 57% rename from chapter_3/lecture_2/src/main/java/Main.java rename to chapter_3_thread_management/lecture_2_thread_priorities_and_state/src/main/java/Main.java index 952f59b..5778176 100644 --- a/chapter_3/lecture_2/src/main/java/Main.java +++ b/chapter_3_thread_management/lecture_2_thread_priorities_and_state/src/main/java/Main.java @@ -1,23 +1,28 @@ +// Chapter 3 Lecture 2: Thread Priority and States + +import javax.swing.plaf.TableHeaderUI; + public class Main { // public static void main(String[] args) throws InterruptedException { +// // main thread // Thread.currentThread().setPriority(Thread.MAX_PRIORITY); // +// // new thread // Thread thread1 = new Thread(() -> { // Thread currentThread = Thread.currentThread(); -// System.out.println(currentThread.getName() + " priority = " + currentThread.getPriority()); +// System.out.println(currentThread.getName() + ": priority = " + currentThread.getPriority()); // }); -// // thread1.setName("Thread_1"); // thread1.setPriority(Thread.MAX_PRIORITY); // // Thread thread2 = new Thread(() -> { // Thread currentThread = Thread.currentThread(); -// System.out.println(currentThread.getName() + " priority = " + currentThread.getPriority()); +// System.out.println(currentThread.getName() + ": priority = " + currentThread.getPriority()); // }); -// // thread2.setName("Thread_2"); // thread2.setPriority(Thread.MIN_PRIORITY); // +// // thread1.start(); // thread2.start(); // @@ -26,19 +31,18 @@ public class Main { // } public static void main(String[] args) throws InterruptedException { + // new thread Thread thread = new Thread(() -> { Thread currentThread = Thread.currentThread(); - System.out.println("[1] State: " + currentThread.getState()); + System.out.println("[1] State: " + currentThread.getState()); // RUNNABLE }); - System.out.println("[2] State: " + thread.getState()); - - thread.start(); - - System.out.println("[3] State: " + thread.getState()); + System.out.println("[2] State: " + thread.getState()); // NEW - thread.join(); + thread.start(); // started new thread + System.out.println("[3] State: " + thread.getState()); // RUNNABLE - System.out.println("[4] State: " + thread.getState()); + thread.join(); // joins main thread + System.out.println("[4] State: " + thread.getState()); // TERMINATE } -} +} \ No newline at end of file diff --git a/chapter_3/lecture_3/build.gradle b/chapter_3_thread_management/lecture_3_thread_groups/build.gradle similarity index 100% rename from chapter_3/lecture_3/build.gradle rename to chapter_3_thread_management/lecture_3_thread_groups/build.gradle diff --git a/chapter_3/lecture_3/gradle/wrapper/gradle-wrapper.jar b/chapter_3_thread_management/lecture_3_thread_groups/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_3/lecture_3/gradle/wrapper/gradle-wrapper.jar rename to chapter_3_thread_management/lecture_3_thread_groups/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_3/lecture_3/gradle/wrapper/gradle-wrapper.properties b/chapter_3_thread_management/lecture_3_thread_groups/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_3/lecture_3/gradle/wrapper/gradle-wrapper.properties rename to chapter_3_thread_management/lecture_3_thread_groups/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_3/lecture_3/gradlew b/chapter_3_thread_management/lecture_3_thread_groups/gradlew similarity index 100% rename from chapter_3/lecture_3/gradlew rename to chapter_3_thread_management/lecture_3_thread_groups/gradlew diff --git a/chapter_3/lecture_3/gradlew.bat b/chapter_3_thread_management/lecture_3_thread_groups/gradlew.bat similarity index 100% rename from chapter_3/lecture_3/gradlew.bat rename to chapter_3_thread_management/lecture_3_thread_groups/gradlew.bat diff --git a/chapter_3/lecture_3/settings.gradle b/chapter_3_thread_management/lecture_3_thread_groups/settings.gradle similarity index 100% rename from chapter_3/lecture_3/settings.gradle rename to chapter_3_thread_management/lecture_3_thread_groups/settings.gradle diff --git a/chapter_3_thread_management/lecture_3_thread_groups/src/main/java/Main.java b/chapter_3_thread_management/lecture_3_thread_groups/src/main/java/Main.java new file mode 100644 index 0000000..a96b40e --- /dev/null +++ b/chapter_3_thread_management/lecture_3_thread_groups/src/main/java/Main.java @@ -0,0 +1,56 @@ +// Chapter 3 Lecture 3: Thread Groups +public class Main { + public static void main(String[] args) throws InterruptedException { +// Thread thread1 = new Thread(() -> System.out.println("Thread1")); +// Thread thread2 = new Thread(() -> System.out.println("Thread2")); +// Thread thread3 = new Thread(() -> System.out.println("Thread3")); +// thread1.start(); +// // ... +// thread1.join(); +// // .. + +// // Instead of above we can be managed by ThreadGroups +// ThreadGroup subGroup = new ThreadGroup("subGroup"); +// ThreadGroup rootGroup = new ThreadGroup(subGroup, "Group1"); // creates child/parent relation +// rootGroup.getParent(); + + // ThreadGroups help manage multiple threads as once + ThreadGroup group1 = new ThreadGroup("Group1"); + + ThreadGroup parent = group1.getParent(); + System.out.println("Parent name: " + parent.getName() + " priority = " + parent.getMaxPriority()); + + group1.setMaxPriority(7); // sets boundary for subgroup threads + + Thread thread1 = new Thread(group1, new MyThread(), "Thread1"); + Thread thread2 = new Thread(group1, new MyThread(), "Thread2"); + Thread thread3 = new Thread(group1, new MyThread(), "Thread3"); + + thread1.setPriority(Thread.MAX_PRIORITY); // will be reduced to groups max priority + + thread1.start(); + thread2.start(); + thread3.start(); + + System.out.println("Sleeping for 3 seconds..."); + Thread.sleep(3000); + +// +// thread1.interrupt(); // lets the thread exit WAITING state + group1.interrupt(); // applies to the whole group fo thread + } + + static class MyThread implements Runnable { + @Override + public void run() { + while (true) { + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + Thread currentThread = Thread.currentThread(); + System.out.println("Name: " + currentThread.getName() + " priority = " + currentThread.getPriority()); + } + } + } + } +} diff --git a/chapter_3/lecture_4/build.gradle b/chapter_3_thread_management/lecture_4_daemon_and_user_threads/build.gradle similarity index 100% rename from chapter_3/lecture_4/build.gradle rename to chapter_3_thread_management/lecture_4_daemon_and_user_threads/build.gradle diff --git a/chapter_3/lecture_4/gradle/wrapper/gradle-wrapper.jar b/chapter_3_thread_management/lecture_4_daemon_and_user_threads/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_3/lecture_4/gradle/wrapper/gradle-wrapper.jar rename to chapter_3_thread_management/lecture_4_daemon_and_user_threads/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_3/lecture_4/gradle/wrapper/gradle-wrapper.properties b/chapter_3_thread_management/lecture_4_daemon_and_user_threads/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_3/lecture_4/gradle/wrapper/gradle-wrapper.properties rename to chapter_3_thread_management/lecture_4_daemon_and_user_threads/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_3/lecture_4/gradlew b/chapter_3_thread_management/lecture_4_daemon_and_user_threads/gradlew similarity index 100% rename from chapter_3/lecture_4/gradlew rename to chapter_3_thread_management/lecture_4_daemon_and_user_threads/gradlew diff --git a/chapter_3/lecture_4/gradlew.bat b/chapter_3_thread_management/lecture_4_daemon_and_user_threads/gradlew.bat similarity index 100% rename from chapter_3/lecture_4/gradlew.bat rename to chapter_3_thread_management/lecture_4_daemon_and_user_threads/gradlew.bat diff --git a/chapter_3/lecture_4/settings.gradle b/chapter_3_thread_management/lecture_4_daemon_and_user_threads/settings.gradle similarity index 100% rename from chapter_3/lecture_4/settings.gradle rename to chapter_3_thread_management/lecture_4_daemon_and_user_threads/settings.gradle diff --git a/chapter_3/lecture_4/src/main/java/Main.java b/chapter_3_thread_management/lecture_4_daemon_and_user_threads/src/main/java/Main.java similarity index 53% rename from chapter_3/lecture_4/src/main/java/Main.java rename to chapter_3_thread_management/lecture_4_daemon_and_user_threads/src/main/java/Main.java index 8fd4627..5f8750c 100644 --- a/chapter_3/lecture_4/src/main/java/Main.java +++ b/chapter_3_thread_management/lecture_4_daemon_and_user_threads/src/main/java/Main.java @@ -1,21 +1,25 @@ +// Chapter 3 Lecture 4: Daemon Threads and User Threads public class Main { public static void main(String[] args) throws InterruptedException { - Thread thread1 = new Thread(new MyThread(10), "Thread1"); - Thread thread2 = new Thread(new MyThread(3), "Thread2"); + Thread thread1 = new Thread(new MyThread(10), "Thread1"); // converted to daemon thread + Thread thread2 = new Thread(new MyThread(3), "Thread2"); // user thread - thread1.setDaemon(true); + // considered low priority by jvm + // not required to be completed before the jvm exits + // in this example, thread1 will exit with thread2 finishes + thread1.setDaemon(true); // daemon thread thread1.start(); thread2.start(); + // joining daemon thread will make the jvm to wait until the thread is complete (user thread like) + // example above, thread1 will print all 10 seconds thread1.join(); - thread2.join(); } static class MyThread implements Runnable { private final int numberOfSeconds; - - public MyThread(int numberOfSeconds) { + public MyThread (int numberOfSeconds) { this.numberOfSeconds = numberOfSeconds; } @@ -23,12 +27,11 @@ public MyThread(int numberOfSeconds) { public void run() { for (int i = 0; i < numberOfSeconds; i++) { try { - System.out.println("Sleeping for 1s, thread: " + Thread.currentThread().getName()); + System.out.println("Sleeping for 1 second, thread: " + Thread.currentThread().getName()); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } - } -} + }} \ No newline at end of file diff --git a/chapter_3/lecture_5/build.gradle b/chapter_3_thread_management/lecture_5_thread_exception_handling/build.gradle similarity index 100% rename from chapter_3/lecture_5/build.gradle rename to chapter_3_thread_management/lecture_5_thread_exception_handling/build.gradle diff --git a/chapter_3/lecture_5/gradle/wrapper/gradle-wrapper.jar b/chapter_3_thread_management/lecture_5_thread_exception_handling/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_3/lecture_5/gradle/wrapper/gradle-wrapper.jar rename to chapter_3_thread_management/lecture_5_thread_exception_handling/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_3/lecture_5/gradle/wrapper/gradle-wrapper.properties b/chapter_3_thread_management/lecture_5_thread_exception_handling/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_3/lecture_5/gradle/wrapper/gradle-wrapper.properties rename to chapter_3_thread_management/lecture_5_thread_exception_handling/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_3/lecture_5/gradlew b/chapter_3_thread_management/lecture_5_thread_exception_handling/gradlew similarity index 100% rename from chapter_3/lecture_5/gradlew rename to chapter_3_thread_management/lecture_5_thread_exception_handling/gradlew diff --git a/chapter_3/lecture_5/gradlew.bat b/chapter_3_thread_management/lecture_5_thread_exception_handling/gradlew.bat similarity index 100% rename from chapter_3/lecture_5/gradlew.bat rename to chapter_3_thread_management/lecture_5_thread_exception_handling/gradlew.bat diff --git a/chapter_3/lecture_5/settings.gradle b/chapter_3_thread_management/lecture_5_thread_exception_handling/settings.gradle similarity index 100% rename from chapter_3/lecture_5/settings.gradle rename to chapter_3_thread_management/lecture_5_thread_exception_handling/settings.gradle diff --git a/chapter_3/lecture_5/src/main/java/Main.java b/chapter_3_thread_management/lecture_5_thread_exception_handling/src/main/java/Main.java similarity index 60% rename from chapter_3/lecture_5/src/main/java/Main.java rename to chapter_3_thread_management/lecture_5_thread_exception_handling/src/main/java/Main.java index 4386b65..b317066 100644 --- a/chapter_3/lecture_5/src/main/java/Main.java +++ b/chapter_3_thread_management/lecture_5_thread_exception_handling/src/main/java/Main.java @@ -1,16 +1,17 @@ import java.util.List; +// Chapter 3 Lecture 5 - Thread Exception Handling public class Main { public static void main(String[] args) throws InterruptedException { - Thread thread1 = new Thread(new CustomThreadGroup("group1"), new MyThread(1), "Thread1"); + Thread thread1 = new Thread(new MyThread(1), "Thread1"); - Thread.setDefaultUncaughtExceptionHandler((Thread t, Throwable exception) -> { - System.out.println(exception.getMessage()); - }); + Thread.setDefaultUncaughtExceptionHandler( + (Thread t, Throwable exception) -> System.out.println(exception.getMessage()) + ); -// thread1.setUncaughtExceptionHandler((Thread t, Throwable exception) -> { -// System.out.println(exception.getMessage()); -// }); + thread1.setUncaughtExceptionHandler( + (Thread t, Throwable exception) -> System.out.println(exception.getMessage()) + ); thread1.start(); thread1.join(); @@ -29,22 +30,21 @@ public CustomThreadGroup(ThreadGroup parent, String name) { @Override public void uncaughtException(Thread t, Throwable e) { super.uncaughtException(t, e); - System.out.println(e.getMessage()); + System.out.println("Thread: "+ t + e.getMessage()); } } static class MyThread implements Runnable { private final int numberOfSeconds; - - public MyThread(int numberOfSeconds) { + public MyThread (int numberOfSeconds) { this.numberOfSeconds = numberOfSeconds; } @Override public void run() { - for(int i = 0; i < numberOfSeconds; i++) { + for (int i = 0; i < numberOfSeconds; i++) { try { - System.out.println("Sleeping for 1s, thread: " + Thread.currentThread().getName()); + System.out.println("Sleeping for 1 second, thread: " + Thread.currentThread().getName()); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); @@ -56,4 +56,4 @@ public void run() { System.out.println("Result: " + (4 / 0)); } } -} +} \ No newline at end of file diff --git a/chapter_3/lecture_6/build.gradle b/chapter_3_thread_management/lecture_6_thread_local_variable_and_race_conditions/build.gradle similarity index 100% rename from chapter_3/lecture_6/build.gradle rename to chapter_3_thread_management/lecture_6_thread_local_variable_and_race_conditions/build.gradle diff --git a/chapter_3/lecture_6/gradle/wrapper/gradle-wrapper.jar b/chapter_3_thread_management/lecture_6_thread_local_variable_and_race_conditions/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_3/lecture_6/gradle/wrapper/gradle-wrapper.jar rename to chapter_3_thread_management/lecture_6_thread_local_variable_and_race_conditions/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_3/lecture_6/gradle/wrapper/gradle-wrapper.properties b/chapter_3_thread_management/lecture_6_thread_local_variable_and_race_conditions/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_3/lecture_6/gradle/wrapper/gradle-wrapper.properties rename to chapter_3_thread_management/lecture_6_thread_local_variable_and_race_conditions/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_3/lecture_6/gradlew b/chapter_3_thread_management/lecture_6_thread_local_variable_and_race_conditions/gradlew similarity index 100% rename from chapter_3/lecture_6/gradlew rename to chapter_3_thread_management/lecture_6_thread_local_variable_and_race_conditions/gradlew diff --git a/chapter_3/lecture_6/gradlew.bat b/chapter_3_thread_management/lecture_6_thread_local_variable_and_race_conditions/gradlew.bat similarity index 100% rename from chapter_3/lecture_6/gradlew.bat rename to chapter_3_thread_management/lecture_6_thread_local_variable_and_race_conditions/gradlew.bat diff --git a/chapter_3/lecture_6/settings.gradle b/chapter_3_thread_management/lecture_6_thread_local_variable_and_race_conditions/settings.gradle similarity index 100% rename from chapter_3/lecture_6/settings.gradle rename to chapter_3_thread_management/lecture_6_thread_local_variable_and_race_conditions/settings.gradle diff --git a/chapter_3_thread_management/lecture_6_thread_local_variable_and_race_conditions/src/main/java/Main.java b/chapter_3_thread_management/lecture_6_thread_local_variable_and_race_conditions/src/main/java/Main.java new file mode 100644 index 0000000..a8cfdd9 --- /dev/null +++ b/chapter_3_thread_management/lecture_6_thread_local_variable_and_race_conditions/src/main/java/Main.java @@ -0,0 +1 @@ +ide \ No newline at end of file diff --git a/chapter_3/lecture_7/build.gradle b/chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/build.gradle similarity index 100% rename from chapter_3/lecture_7/build.gradle rename to chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/build.gradle diff --git a/chapter_3/lecture_7/file1.txt_processing b/chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/file1.txt_processing similarity index 100% rename from chapter_3/lecture_7/file1.txt_processing rename to chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/file1.txt_processing diff --git a/chapter_3/lecture_7/gradle/wrapper/gradle-wrapper.jar b/chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_3/lecture_7/gradle/wrapper/gradle-wrapper.jar rename to chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_3/lecture_7/gradle/wrapper/gradle-wrapper.properties b/chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_3/lecture_7/gradle/wrapper/gradle-wrapper.properties rename to chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_3/lecture_7/gradlew b/chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/gradlew similarity index 100% rename from chapter_3/lecture_7/gradlew rename to chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/gradlew diff --git a/chapter_3/lecture_7/gradlew.bat b/chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/gradlew.bat similarity index 100% rename from chapter_3/lecture_7/gradlew.bat rename to chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/gradlew.bat diff --git a/chapter_3/lecture_7/settings.gradle b/chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/settings.gradle similarity index 100% rename from chapter_3/lecture_7/settings.gradle rename to chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/settings.gradle diff --git a/chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/src/main/java/Main.java b/chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/src/main/java/Main.java new file mode 100644 index 0000000..825b962 --- /dev/null +++ b/chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/src/main/java/Main.java @@ -0,0 +1,203 @@ +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +/** + * === REQUIREMENTS === + * 1. Periodically scans the ./src/main/resources directory and watches for new files + * 2. For each file found into this directory, a new thread should take care of its processing + * 3. Processing = each line of the file will be hashed using a hashing algorithm + * 4. The program will create new files, marked _output suffix, and they will placed into ./src/main/output + * 5. Throw an exception if a line is empty + */ + +public class Main { + // local caching to track process files to not process them more than once + // Not a perfect solution due to a new thread being created per file and running in parallel + // Some files will still be re-run more than once due to race condition where a file is still being processed + // but a new thread gets created for said file before added to the map + // some potential improvements: + // 1. increase sleep timer - will give process more time to add file to map before new thread starts (reduce re-runs of the same file) + // 2. add file to map before completing the process - risk file has an error and marked as "successful" when in fact it failed (file misses) + // 3. add a "pending" state where it shows the file is in progress so that the new thread doesn't work on processing the file <---- best choice + + // static Map> processedFiles = new HashMap<>(); // Not a perfect solution due to race conditions + + /* + * improved but not perfect: adding "volatile" keyword seems to have helped with race condition issue where the same file was being + * processed more than once - tried about 20 times + * this is due to the shared variable been up-to-date since it's getting the value from the main memory instead + * of the thread's cache which can be stale since there's a delay between the main memory and cache being synced + * + * This can still lead to a race condition but for this specific setup it doesn't since it's basic enough + * */ + // static volatile Map> processedFiles = new HashMap<>(); // first improvement - not great but can help in basic usages, if complex can still lead to raise condition + + /** + * A better way is to use concurrent datastructures that are thread safe such as + * "Collections.synchronizedMap(new HashMap<>())" or "new ConcurrentHashMap<>()". + * ConcurrentHashMap has better performance and no need to manually synchronize when iterating map; however it + * has a higher memory overhead. For simple scenarios Collections.synchronizedMap can work. + * For concurrency applications using ConcurrentHashMap is much better. + * + * Concurrent datastructures are thread safe due to the following being done under the hood: + * fine grain locking, atomic updates without fulling locking, using linked list and trees + * for better collision handling, and better use of volatile variables. + */ + static Map> processedFiles = new ConcurrentHashMap<>(); + + public static void main(String[] args) { + new Thread(new Watcher(processedFiles)).start(); + } +} + +class ExceptionHandler implements Thread.UncaughtExceptionHandler { + private final File file; + Map> processedFiles; + String PENDING = "pending"; + String FAILED = "failed"; + + public ExceptionHandler(Map> processedFiles, File file) { + this.processedFiles = processedFiles; + this.file = file; + } + + @Override + public void uncaughtException(Thread t, Throwable e) { + processedFiles.get(PENDING).remove(file.getName()); + processedFiles.get(FAILED).add(file.getName()); + System.out.println("Files failed to process: " + processedFiles.get(FAILED)); + System.out.println("Exception handled: " + e.getMessage()); + } +} + +class Watcher implements Runnable { + Map> processedFiles; + String SUCCESSFUL = "successful"; + String PENDING = "pending"; + String FAILED = "failed"; + + public Watcher(Map> processedFiles) { + this.processedFiles = processedFiles; + this.processedFiles.put(SUCCESSFUL, new HashSet<>()); + this.processedFiles.put(PENDING, new HashSet<>()); + this.processedFiles.put(FAILED, new HashSet<>()); + } + + @Override + public void run() { + File inputDirectory = new File("./src/main/resources"); + + while (true) { + if (inputDirectory.listFiles().length != 0) { + Arrays.stream(inputDirectory.listFiles()).forEach( + file -> { + boolean fileIsNotInSuccessful = !processedFiles.get(SUCCESSFUL).contains(file.getName()); + boolean fileIsNotInPending = !processedFiles.get(PENDING).contains(file.getName()); + if (fileIsNotInSuccessful && fileIsNotInPending) { + /** When "volatile" wasn't used for processedFiles there was a weird situation where + * ```Thread t = new Thread(new FileProcessor(file, processedFiles));``` + * leads to a race condition compared to variable reference when tried over 20 times each + * ```FileProcessor proc = new FileProcessor(file, processedFiles); + * Thread t = new Thread(proc);``` + * I would have expected both method to have the same behaviour but doesn't seem to be the case + * I wonder if the variable reference slows down the thread enough to + * 1. give Thread1 enough time to update the map and Thread2 to read that file is "pending" OR + * 2. read from the `processedFiles` map where the cached variable has been synced with the main memory + */ + Thread t = new Thread(new FileProcessor(file, processedFiles)); + t.setUncaughtExceptionHandler(new ExceptionHandler(processedFiles, file)); + t.start(); + } + } + ); + } + + sleep(); + } + } + + private void sleep() { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +} + +class FileProcessor implements Runnable { + + private final File file; + private final static String OUTPUT_PATH = "./src/main/output/"; + + Map> processedFiles; + String SUCCESSFUL = "successful"; + String PENDING = "pending"; + + public FileProcessor(File file, Map> processedFiles) { + this.file = file; + this.processedFiles = processedFiles; + processedFiles.get(PENDING).add(file.getName()); + } + + @Override + public void run() { + try { + BufferedWriter writer = new BufferedWriter(new FileWriter(OUTPUT_PATH + file.getName())); + + Files.lines(Path.of(file.getCanonicalPath())) + .map(this::hash) + .map(line -> line + "\n") + .forEach(el -> { + try { + writer.write(el); + } catch (IOException e) { + e.printStackTrace(); + } + }); + + writer.close(); + processedFiles.get(SUCCESSFUL).add(file.getName()); + processedFiles.get(PENDING).remove(file.getName()); + } catch (IOException e) { + e.printStackTrace(); + } + System.out.println(Thread.currentThread().getName() + " -> processed file: " + file.getName()); + } + + private String hash(String input) { + if (input.equals("")) { + throw new RuntimeException("The line is empty, hashing cannot be done"); + } + + try { + final MessageDigest digest = MessageDigest.getInstance("SHA3-256"); + final byte[] hashbytes = digest.digest(input.getBytes(StandardCharsets.UTF_8)); + return bytesToHex(hashbytes); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + return ""; + } + } + + private static String bytesToHex(byte[] hash) { + StringBuilder hexString = new StringBuilder(2 * hash.length); + for (int i = 0; i < hash.length; i++) { + String hex = Integer.toHexString(0xff & hash[i]); + if(hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); + } +} \ No newline at end of file diff --git a/chapter_3/lecture_7/src/main/output/file1.txt b/chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/src/main/output/file1.txt similarity index 100% rename from chapter_3/lecture_7/src/main/output/file1.txt rename to chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/src/main/output/file1.txt diff --git a/chapter_3/lecture_7/src/main/output/file2.txt b/chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/src/main/output/file2.txt similarity index 100% rename from chapter_3/lecture_7/src/main/output/file2.txt rename to chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/src/main/output/file2.txt diff --git a/chapter_3/lecture_7/src/main/output/file3.txt b/chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/src/main/output/file3.txt similarity index 100% rename from chapter_3/lecture_7/src/main/output/file3.txt rename to chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/src/main/output/file3.txt diff --git a/chapter_3/lecture_7/src/main/resources/file1.txt b/chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/src/main/resources/file1.txt similarity index 100% rename from chapter_3/lecture_7/src/main/resources/file1.txt rename to chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/src/main/resources/file1.txt diff --git a/chapter_3/lecture_7/src/main/resources/file2.txt b/chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/src/main/resources/file2.txt similarity index 100% rename from chapter_3/lecture_7/src/main/resources/file2.txt rename to chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/src/main/resources/file2.txt diff --git a/chapter_3/lecture_7/src/main/resources/file3.txt b/chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/src/main/resources/file3.txt similarity index 100% rename from chapter_3/lecture_7/src/main/resources/file3.txt rename to chapter_3_thread_management/lecture_7_project_parallel_text_file_processing/src/main/resources/file3.txt diff --git a/chapter_4/lecture_2/src/main/java/Main.java b/chapter_4/lecture_2/src/main/java/Main.java deleted file mode 100644 index d6ff69b..0000000 --- a/chapter_4/lecture_2/src/main/java/Main.java +++ /dev/null @@ -1,63 +0,0 @@ -import java.util.ArrayList; -import java.util.List; - -public class Main { - - private static int globalCounter = 0; - private static final Object obj = new Object(); - - public static void main(String[] args) { - List threads = new ArrayList<>(); - - ThreadGroup group = new ThreadGroup("Group1"); - - for (int i = 1; i<=1000; i++) { - Thread t = new Thread(group, new MyThread()); - t.start(); - threads.add(t); - } - - group.interrupt(); - - threads.forEach(t -> { - try { - t.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - }); - - System.out.println("Total = " + globalCounter); - } - - static class MyThread implements Runnable { - @Override - public void run() { - try { - Thread.sleep(99999); - } catch (InterruptedException e) { - - } - synchronized (obj) { - globalCounter++; - } - - -// int localCounter = globalCounter; -// localCounter = localCounter + 1; -// globalCounter = localCounter; - } - - private static void staticIncrement() { - synchronized (MyThread.class) { - - } - } - - private void increment() { - synchronized (this) { - - } - } - } -} diff --git a/chapter_4/lecture_4/src/main/java/Main.java b/chapter_4/lecture_4/src/main/java/Main.java deleted file mode 100644 index 33b0846..0000000 --- a/chapter_4/lecture_4/src/main/java/Main.java +++ /dev/null @@ -1,52 +0,0 @@ -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.locks.ReentrantLock; - -public class Main { - - private static int[] array = new int[10]; - private static int arrayLength = 10; - private static int numberOfThreads = 2; - private static int sum = 0; - private static ReentrantLock mutex = new ReentrantLock(); - - public static void main(String[] args) throws InterruptedException { - for (int i = 0; i < arrayLength; i++) { - array[i] = 10; - } - - List threads = new ArrayList<>(); - int threadSlice = arrayLength / numberOfThreads; - - for (int i = 0; i < numberOfThreads; i++) { - Thread t = new Thread(new MyThread(i * threadSlice, (i + 1) * threadSlice)); - t.start(); - threads.add(t); - } - - for (Thread thread : threads) { - thread.join(); - } - - System.out.println("Sum is: " + sum); - } - - static class MyThread implements Runnable { - private final int left; - private final int right; - - public MyThread(int left, int right) { - this.left = left; - this.right = right; - } - - @Override - public void run() { - for (int i = left; i < right; i++) { - mutex.lock(); - sum = sum + array[i]; - mutex.unlock(); - } - } - } -} diff --git a/chapter_4/lecture_7/src/main/java/Main.java b/chapter_4/lecture_7/src/main/java/Main.java deleted file mode 100644 index 8b6cc27..0000000 --- a/chapter_4/lecture_7/src/main/java/Main.java +++ /dev/null @@ -1,51 +0,0 @@ -import java.util.concurrent.Semaphore; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -public class Main { - - private static Semaphore semaphore = new Semaphore(2); - - public static void main(String[] args) throws InterruptedException { - - Executor executor = new Executor(); - - executor.submit(new Job(4000)); - executor.submit(new Job(5000)); - executor.submit(new Job(3000)); - } - - static class Executor { - public void submit(Job job) throws InterruptedException { - System.out.println("Launching job " + job.getWork()); - semaphore.acquire(); - - Thread t = new Thread(() -> { - try { - System.out.println("Executing job " + job.getWork()); - Thread.sleep(job.getWork()); - - semaphore.release(); - System.out.println("Job finished with id " + job.getWork()); - - } catch (InterruptedException e) { - e.printStackTrace(); - } - }); - - t.start(); - } - } - - static class Job { - private final int work; - - public Job(int work) { - this.work = work; - } - - public int getWork() { - return work; - } - } -} diff --git a/chapter_4/lecture_2/build.gradle b/chapter_4_thread_synchronization_part1/lecture_2_synchronized_keyword/build.gradle similarity index 100% rename from chapter_4/lecture_2/build.gradle rename to chapter_4_thread_synchronization_part1/lecture_2_synchronized_keyword/build.gradle diff --git a/chapter_4/lecture_2/gradle/wrapper/gradle-wrapper.jar b/chapter_4_thread_synchronization_part1/lecture_2_synchronized_keyword/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_4/lecture_2/gradle/wrapper/gradle-wrapper.jar rename to chapter_4_thread_synchronization_part1/lecture_2_synchronized_keyword/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_4/lecture_2/gradle/wrapper/gradle-wrapper.properties b/chapter_4_thread_synchronization_part1/lecture_2_synchronized_keyword/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_4/lecture_2/gradle/wrapper/gradle-wrapper.properties rename to chapter_4_thread_synchronization_part1/lecture_2_synchronized_keyword/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_4/lecture_2/gradlew b/chapter_4_thread_synchronization_part1/lecture_2_synchronized_keyword/gradlew similarity index 100% rename from chapter_4/lecture_2/gradlew rename to chapter_4_thread_synchronization_part1/lecture_2_synchronized_keyword/gradlew diff --git a/chapter_4/lecture_2/gradlew.bat b/chapter_4_thread_synchronization_part1/lecture_2_synchronized_keyword/gradlew.bat similarity index 100% rename from chapter_4/lecture_2/gradlew.bat rename to chapter_4_thread_synchronization_part1/lecture_2_synchronized_keyword/gradlew.bat diff --git a/chapter_4/lecture_2/settings.gradle b/chapter_4_thread_synchronization_part1/lecture_2_synchronized_keyword/settings.gradle similarity index 100% rename from chapter_4/lecture_2/settings.gradle rename to chapter_4_thread_synchronization_part1/lecture_2_synchronized_keyword/settings.gradle diff --git a/chapter_3/lecture_6/src/main/java/Main.java b/chapter_4_thread_synchronization_part1/lecture_2_synchronized_keyword/src/main/java/Main.java similarity index 54% rename from chapter_3/lecture_6/src/main/java/Main.java rename to chapter_4_thread_synchronization_part1/lecture_2_synchronized_keyword/src/main/java/Main.java index 0bba3b5..50a2cc5 100644 --- a/chapter_3/lecture_6/src/main/java/Main.java +++ b/chapter_4_thread_synchronization_part1/lecture_2_synchronized_keyword/src/main/java/Main.java @@ -1,9 +1,13 @@ +// Code taken from Chapter 3 Lecture 6: Thread Local Variables and Race Conditions +// Added synchronized block and synchronized method + + import java.util.ArrayList; import java.util.List; public class Main { - private static int globalCounter = 0; + private static final Object obj = new Object(); public static void main(String[] args) { List threads = new ArrayList<>(); @@ -34,25 +38,44 @@ static class MyThread implements Runnable { public void run() { try { Thread.sleep(99999); - } catch (InterruptedException e) { + } catch (InterruptedException ignored) { } - globalCounter++; + // synchronized block - more granular control + synchronized (obj) { // object should be accessible to all the thread + globalCounter++; + } + +// // Race Condition issue!! +// // problem with this is that if multiple threads share a global variable and read variable value the same +// // example: running 3 threads, where thread 1 and 3 both read the globalCounter=1, +// // then both threads increment globalCounter to 2 instead of 3 (1 -> thread1++1 -> thread3++1 -> 3) +// // race condition behaviour: (1 -> thread1++1 -> [2] +// // 1 -> thread3++1 -> [2]) +// // expected behaviour: (1 -> thread1++1 -> 2 -> thread3++1 -> [3]) // int localCounter = globalCounter; // localCounter = localCounter + 1; // globalCounter = localCounter; + } + +// // synchronized method (equivalent to synchronized block) +// private synchronized void increment() { +// +// } } +// private static ThreadLocal threadLocal = new ThreadLocal<>(); // private static ThreadLocal threadLocal = ThreadLocal.withInitial(() -> "initialValue"); -// + // public static void main(String[] args) { // Thread t1 = new Thread(new MyThread()); // Thread t2 = new Thread(new MyThread()); // // t1.start(); // t2.start(); +// // } // // static class MyThread implements Runnable { @@ -62,6 +85,9 @@ public void run() { // // threadLocal.set("myValue"); // threadLocal.get(); +// +// System.out.println("ThreadLocal: " + threadLocal.get()); // } // } -} + +} \ No newline at end of file diff --git a/chapter_4/lecture_3/build.gradle b/chapter_4_thread_synchronization_part1/lecture_3_wait_sets_and_notifications/build.gradle similarity index 100% rename from chapter_4/lecture_3/build.gradle rename to chapter_4_thread_synchronization_part1/lecture_3_wait_sets_and_notifications/build.gradle diff --git a/chapter_4/lecture_3/gradle/wrapper/gradle-wrapper.jar b/chapter_4_thread_synchronization_part1/lecture_3_wait_sets_and_notifications/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_4/lecture_3/gradle/wrapper/gradle-wrapper.jar rename to chapter_4_thread_synchronization_part1/lecture_3_wait_sets_and_notifications/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_4/lecture_3/gradle/wrapper/gradle-wrapper.properties b/chapter_4_thread_synchronization_part1/lecture_3_wait_sets_and_notifications/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_4/lecture_3/gradle/wrapper/gradle-wrapper.properties rename to chapter_4_thread_synchronization_part1/lecture_3_wait_sets_and_notifications/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_4/lecture_3/gradlew b/chapter_4_thread_synchronization_part1/lecture_3_wait_sets_and_notifications/gradlew similarity index 100% rename from chapter_4/lecture_3/gradlew rename to chapter_4_thread_synchronization_part1/lecture_3_wait_sets_and_notifications/gradlew diff --git a/chapter_4/lecture_3/gradlew.bat b/chapter_4_thread_synchronization_part1/lecture_3_wait_sets_and_notifications/gradlew.bat similarity index 100% rename from chapter_4/lecture_3/gradlew.bat rename to chapter_4_thread_synchronization_part1/lecture_3_wait_sets_and_notifications/gradlew.bat diff --git a/chapter_4/lecture_3/settings.gradle b/chapter_4_thread_synchronization_part1/lecture_3_wait_sets_and_notifications/settings.gradle similarity index 100% rename from chapter_4/lecture_3/settings.gradle rename to chapter_4_thread_synchronization_part1/lecture_3_wait_sets_and_notifications/settings.gradle diff --git a/chapter_4/lecture_3/src/main/java/Main.java b/chapter_4_thread_synchronization_part1/lecture_3_wait_sets_and_notifications/src/main/java/Main.java similarity index 75% rename from chapter_4/lecture_3/src/main/java/Main.java rename to chapter_4_thread_synchronization_part1/lecture_3_wait_sets_and_notifications/src/main/java/Main.java index 2258a3d..de27c92 100644 --- a/chapter_4/lecture_3/src/main/java/Main.java +++ b/chapter_4_thread_synchronization_part1/lecture_3_wait_sets_and_notifications/src/main/java/Main.java @@ -39,28 +39,29 @@ public Producer(Queue queue) { @Override public void run() { - while(true) { + while (true) { try { - produceData(); + producerData(); } catch (InterruptedException e) { - e.printStackTrace(); + throw new RuntimeException(e); } } } - private void produceData() throws InterruptedException { + private void producerData() throws InterruptedException { synchronized (queue) { if (queue.size() == 10) { - System.out.println("In producer, waiting..."); + System.out.println("In producer, waiting ..."); queue.wait(); } - Thread.sleep(1000); + Thread.sleep(500); System.out.println("Producing data with id " + queue.size()); queue.add("element_" + queue.size()); if (queue.size() == 1) { + // will unlock consumer from the waiting state queue.notify(); } } @@ -68,7 +69,6 @@ private void produceData() throws InterruptedException { } static class Consumer implements Runnable { - private final Queue queue; public Consumer(Queue queue) { @@ -79,26 +79,27 @@ public Consumer(Queue queue) { public void run() { while (true) { try { - consumeData(); + consumerData(); } catch (InterruptedException e) { - e.printStackTrace(); + throw new RuntimeException(e); } } } - private void consumeData() throws InterruptedException { + private void consumerData() throws InterruptedException { synchronized (queue) { if (queue.isEmpty()) { - System.out.println("Consumer is waiting..."); + System.out.println("Consumer is waiting ..."); queue.wait(); } - Thread.sleep(700); + Thread.sleep(250); String data = queue.remove(); - System.out.println("Consumed data: " + data); + System.out.println("Consumer data " + data); if (queue.size() == 9) { + // will unlock producer from the waiting state queue.notify(); } } diff --git a/chapter_4/lecture_4/build.gradle b/chapter_4_thread_synchronization_part1/lecture_4_locks_with_parallel_vector_sum/build.gradle similarity index 100% rename from chapter_4/lecture_4/build.gradle rename to chapter_4_thread_synchronization_part1/lecture_4_locks_with_parallel_vector_sum/build.gradle diff --git a/chapter_4/lecture_4/gradle/wrapper/gradle-wrapper.jar b/chapter_4_thread_synchronization_part1/lecture_4_locks_with_parallel_vector_sum/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_4/lecture_4/gradle/wrapper/gradle-wrapper.jar rename to chapter_4_thread_synchronization_part1/lecture_4_locks_with_parallel_vector_sum/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_4/lecture_4/gradle/wrapper/gradle-wrapper.properties b/chapter_4_thread_synchronization_part1/lecture_4_locks_with_parallel_vector_sum/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_4/lecture_4/gradle/wrapper/gradle-wrapper.properties rename to chapter_4_thread_synchronization_part1/lecture_4_locks_with_parallel_vector_sum/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_4/lecture_4/gradlew b/chapter_4_thread_synchronization_part1/lecture_4_locks_with_parallel_vector_sum/gradlew similarity index 100% rename from chapter_4/lecture_4/gradlew rename to chapter_4_thread_synchronization_part1/lecture_4_locks_with_parallel_vector_sum/gradlew diff --git a/chapter_4/lecture_4/gradlew.bat b/chapter_4_thread_synchronization_part1/lecture_4_locks_with_parallel_vector_sum/gradlew.bat similarity index 100% rename from chapter_4/lecture_4/gradlew.bat rename to chapter_4_thread_synchronization_part1/lecture_4_locks_with_parallel_vector_sum/gradlew.bat diff --git a/chapter_4/lecture_4/settings.gradle b/chapter_4_thread_synchronization_part1/lecture_4_locks_with_parallel_vector_sum/settings.gradle similarity index 100% rename from chapter_4/lecture_4/settings.gradle rename to chapter_4_thread_synchronization_part1/lecture_4_locks_with_parallel_vector_sum/settings.gradle diff --git a/chapter_4_thread_synchronization_part1/lecture_4_locks_with_parallel_vector_sum/src/main/java/Main.java b/chapter_4_thread_synchronization_part1/lecture_4_locks_with_parallel_vector_sum/src/main/java/Main.java new file mode 100644 index 0000000..fd8ccf3 --- /dev/null +++ b/chapter_4_thread_synchronization_part1/lecture_4_locks_with_parallel_vector_sum/src/main/java/Main.java @@ -0,0 +1,81 @@ +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +public class Main { + + private static int S = 0; + private static int[] array = new int[10]; + private static ReentrantLock lockObject = new ReentrantLock(); + +// public static void main(String[] args) { +// Lock lockObject = new ReentrantLock(); +// +//// synchronized (new Object()) { +//// } +// +// lockObject.tryLock(); // non-blocking, returns boolean if the lock is released or not +// +// lockObject.lock(); +// lockObject.lock(); +// lockObject.lock(); +// +// // Thread 1 is holding the lock +// System.out.println("Instruction"); +// +// lockObject.unlock(); +// +//// try { +//// } catch (Exception ignored) { +//// } finally { +//// lockObject.unlock(); +//// } +// } + + public static void main(String[] args) { + for (int i = 0; i < 10; i++) { + array[i] = 10; + } + + List threadList = new ArrayList<>(); + + int threadSlice = array.length / 2; + + // will create and execute 2 threads + for (int i = 0; i < 2; i++) { + Thread t = new Thread(new WorkerThread(i * threadSlice, (i + 1) * threadSlice)); + t.start(); + threadList.add(t); + } + + threadList.forEach(t -> { + try { + t.join(); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + + System.out.println("The sum is: " + S); + } + + static class WorkerThread implements Runnable { + private final int left; + private final int right; + public WorkerThread(int left, int right) { + this.left = left; + this.right = right; + } + + @Override + public void run() { + for (int i = left; i < right; i++) { + lockObject.lock(); + S = S + array[i]; // critical section + lockObject.unlock(); + } + } + } + +} diff --git a/chapter_4/lecture_5/build.gradle b/chapter_4_thread_synchronization_part1/lecture_5_readwrite_locks_and_spin_locks/build.gradle similarity index 100% rename from chapter_4/lecture_5/build.gradle rename to chapter_4_thread_synchronization_part1/lecture_5_readwrite_locks_and_spin_locks/build.gradle diff --git a/chapter_4/lecture_5/gradle/wrapper/gradle-wrapper.jar b/chapter_4_thread_synchronization_part1/lecture_5_readwrite_locks_and_spin_locks/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_4/lecture_5/gradle/wrapper/gradle-wrapper.jar rename to chapter_4_thread_synchronization_part1/lecture_5_readwrite_locks_and_spin_locks/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_4/lecture_5/gradle/wrapper/gradle-wrapper.properties b/chapter_4_thread_synchronization_part1/lecture_5_readwrite_locks_and_spin_locks/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_4/lecture_5/gradle/wrapper/gradle-wrapper.properties rename to chapter_4_thread_synchronization_part1/lecture_5_readwrite_locks_and_spin_locks/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_4/lecture_5/gradlew b/chapter_4_thread_synchronization_part1/lecture_5_readwrite_locks_and_spin_locks/gradlew similarity index 100% rename from chapter_4/lecture_5/gradlew rename to chapter_4_thread_synchronization_part1/lecture_5_readwrite_locks_and_spin_locks/gradlew diff --git a/chapter_4/lecture_5/gradlew.bat b/chapter_4_thread_synchronization_part1/lecture_5_readwrite_locks_and_spin_locks/gradlew.bat similarity index 100% rename from chapter_4/lecture_5/gradlew.bat rename to chapter_4_thread_synchronization_part1/lecture_5_readwrite_locks_and_spin_locks/gradlew.bat diff --git a/chapter_4/lecture_5/settings.gradle b/chapter_4_thread_synchronization_part1/lecture_5_readwrite_locks_and_spin_locks/settings.gradle similarity index 100% rename from chapter_4/lecture_5/settings.gradle rename to chapter_4_thread_synchronization_part1/lecture_5_readwrite_locks_and_spin_locks/settings.gradle diff --git a/chapter_4/lecture_5/src/main/java/Main.java b/chapter_4_thread_synchronization_part1/lecture_5_readwrite_locks_and_spin_locks/src/main/java/Main.java similarity index 70% rename from chapter_4/lecture_5/src/main/java/Main.java rename to chapter_4_thread_synchronization_part1/lecture_5_readwrite_locks_and_spin_locks/src/main/java/Main.java index 954966d..dc153cb 100644 --- a/chapter_4/lecture_5/src/main/java/Main.java +++ b/chapter_4_thread_synchronization_part1/lecture_5_readwrite_locks_and_spin_locks/src/main/java/Main.java @@ -2,40 +2,42 @@ import java.util.List; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; public class Main { - private static ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); private static Lock readLock = readWriteLock.readLock(); - private static Lock writeLock = readWriteLock.writeLock(); - + private static Lock writeLock = readWriteLock.writeLock(); // write locks have priority private static List list = new ArrayList<>(); +// public static void main(String[] args) { +// Lock lock = new ReentrantLock(); +// lock.lock(); // remember to call unlock for each lock (useful to use with try/catch/finally) +// // try to keep critical sections small as possible +// lock.unlock(); // can be used for read or write +// } public static void main(String[] args) { Thread writer = new Thread(new WriterThread()); Thread reader1 = new Thread(new ReaderThread()); Thread reader2 = new Thread(new ReaderThread()); Thread reader3 = new Thread(new ReaderThread()); - Thread reader4 = new Thread(new ReaderThread()); writer.start(); reader1.start(); reader2.start(); reader3.start(); - reader4.start(); } static class WriterThread implements Runnable { - @Override public void run() { while(true) { try { writeData(); } catch (InterruptedException e) { - e.printStackTrace(); + throw new RuntimeException(e); } } } @@ -45,6 +47,7 @@ private void writeData() throws InterruptedException { writeLock.lock(); + // critical section int value = (int) (Math.random() * 10); System.out.println("Producing data: " + value); @@ -57,21 +60,25 @@ private void writeData() throws InterruptedException { } static class ReaderThread implements Runnable { - @Override public void run() { while(true) { try { readData(); } catch (InterruptedException e) { - e.printStackTrace(); + throw new RuntimeException(e); } } + } private void readData() throws InterruptedException { Thread.sleep(3000); +// readLock.lock(); - without the "spin lock", it keeps the lock in the "waiting state" + + // "spin lock" - will keep the lock in "runnable state" until the lock is available + // useful when blocking is undesirable such as OS Kernels while (true) { boolean acquired = readLock.tryLock(); if (acquired) { @@ -81,8 +88,13 @@ private void readData() throws InterruptedException { } } + // critical section System.out.println("List is: " + list); + readLock.unlock(); } } + + + } diff --git a/chapter_4/lecture_6/build.gradle b/chapter_4_thread_synchronization_part1/lecture_6_condition_variable/build.gradle similarity index 100% rename from chapter_4/lecture_6/build.gradle rename to chapter_4_thread_synchronization_part1/lecture_6_condition_variable/build.gradle diff --git a/chapter_4/lecture_6/gradle/wrapper/gradle-wrapper.jar b/chapter_4_thread_synchronization_part1/lecture_6_condition_variable/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_4/lecture_6/gradle/wrapper/gradle-wrapper.jar rename to chapter_4_thread_synchronization_part1/lecture_6_condition_variable/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_4/lecture_6/gradle/wrapper/gradle-wrapper.properties b/chapter_4_thread_synchronization_part1/lecture_6_condition_variable/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_4/lecture_6/gradle/wrapper/gradle-wrapper.properties rename to chapter_4_thread_synchronization_part1/lecture_6_condition_variable/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_4/lecture_6/gradlew b/chapter_4_thread_synchronization_part1/lecture_6_condition_variable/gradlew similarity index 100% rename from chapter_4/lecture_6/gradlew rename to chapter_4_thread_synchronization_part1/lecture_6_condition_variable/gradlew diff --git a/chapter_4/lecture_6/gradlew.bat b/chapter_4_thread_synchronization_part1/lecture_6_condition_variable/gradlew.bat similarity index 100% rename from chapter_4/lecture_6/gradlew.bat rename to chapter_4_thread_synchronization_part1/lecture_6_condition_variable/gradlew.bat diff --git a/chapter_4/lecture_6/settings.gradle b/chapter_4_thread_synchronization_part1/lecture_6_condition_variable/settings.gradle similarity index 100% rename from chapter_4/lecture_6/settings.gradle rename to chapter_4_thread_synchronization_part1/lecture_6_condition_variable/settings.gradle diff --git a/chapter_4/lecture_6/src/main/java/Main.java b/chapter_4_thread_synchronization_part1/lecture_6_condition_variable/src/main/java/Main.java similarity index 60% rename from chapter_4/lecture_6/src/main/java/Main.java rename to chapter_4_thread_synchronization_part1/lecture_6_condition_variable/src/main/java/Main.java index 50e1379..00e2b29 100644 --- a/chapter_4/lecture_6/src/main/java/Main.java +++ b/chapter_4_thread_synchronization_part1/lecture_6_condition_variable/src/main/java/Main.java @@ -8,7 +8,25 @@ public class Main { private static Lock lock = new ReentrantLock(); private static Condition condition = lock.newCondition(); - private static Condition condition1 = lock.newCondition(); + +// public static void main(String[] args) throws InterruptedException { +// // condition await/signal is similar to synchronized blocks +// // the biggest advantage is that await/signal can set multiple conditions per thread while wait/notify can only do 1 object per thread +// // conditions are best for managing multiple threads based on a condition or complex producer-consumer situations +// Condition condition = lock.newCondition(); +// Condition condition1 = lock.newCondition(); +// Condition condition2 = lock.newCondition(); +// +// // Thread 1 +// lock.lock(); +// condition.await(); +// lock.unlock(); +// +// // Thread 2 +// lock.lock(); +// condition.signal(); +// lock.unlock(); +// } public static void main(String[] args) { Queue queue = new LinkedList<>(); @@ -29,16 +47,16 @@ public Producer(Queue queue) { @Override public void run() { - while(true) { + while (true) { try { - produceData(); + producerData(); } catch (InterruptedException e) { - e.printStackTrace(); + throw new RuntimeException(e); } } } - private void produceData() throws InterruptedException { + private void producerData() throws InterruptedException { lock.lock(); if (queue.size() == 10) { System.out.println("In producer, waiting..."); @@ -51,6 +69,7 @@ private void produceData() throws InterruptedException { queue.add("element_" + queue.size()); if (queue.size() == 1) { + // will unlock consumer from the waiting state condition.signal(); } lock.unlock(); @@ -58,7 +77,6 @@ private void produceData() throws InterruptedException { } static class Consumer implements Runnable { - private final Queue queue; public Consumer(Queue queue) { @@ -69,26 +87,27 @@ public Consumer(Queue queue) { public void run() { while (true) { try { - consumeData(); + consumerData(); } catch (InterruptedException e) { - e.printStackTrace(); + throw new RuntimeException(e); } } } - private void consumeData() throws InterruptedException { + private void consumerData() throws InterruptedException { lock.lock(); if (queue.isEmpty()) { - System.out.println("Consumer is waiting..."); + System.out.println("Consumer is waiting ..."); condition.await(); } Thread.sleep(700); String data = queue.remove(); - System.out.println("Consumed data: " + data); + System.out.println("Consumer data: " + data); if (queue.size() == 9) { + // will unlock producer from the waiting state condition.signal(); } lock.unlock(); diff --git a/chapter_4/lecture_7/build.gradle b/chapter_4_thread_synchronization_part1/lecture_7_semaphores/build.gradle similarity index 100% rename from chapter_4/lecture_7/build.gradle rename to chapter_4_thread_synchronization_part1/lecture_7_semaphores/build.gradle diff --git a/chapter_4/lecture_7/gradle/wrapper/gradle-wrapper.jar b/chapter_4_thread_synchronization_part1/lecture_7_semaphores/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_4/lecture_7/gradle/wrapper/gradle-wrapper.jar rename to chapter_4_thread_synchronization_part1/lecture_7_semaphores/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_4/lecture_7/gradle/wrapper/gradle-wrapper.properties b/chapter_4_thread_synchronization_part1/lecture_7_semaphores/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_4/lecture_7/gradle/wrapper/gradle-wrapper.properties rename to chapter_4_thread_synchronization_part1/lecture_7_semaphores/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_4/lecture_7/gradlew b/chapter_4_thread_synchronization_part1/lecture_7_semaphores/gradlew similarity index 100% rename from chapter_4/lecture_7/gradlew rename to chapter_4_thread_synchronization_part1/lecture_7_semaphores/gradlew diff --git a/chapter_4/lecture_7/gradlew.bat b/chapter_4_thread_synchronization_part1/lecture_7_semaphores/gradlew.bat similarity index 100% rename from chapter_4/lecture_7/gradlew.bat rename to chapter_4_thread_synchronization_part1/lecture_7_semaphores/gradlew.bat diff --git a/chapter_4/lecture_7/settings.gradle b/chapter_4_thread_synchronization_part1/lecture_7_semaphores/settings.gradle similarity index 100% rename from chapter_4/lecture_7/settings.gradle rename to chapter_4_thread_synchronization_part1/lecture_7_semaphores/settings.gradle diff --git a/chapter_4_thread_synchronization_part1/lecture_7_semaphores/src/main/java/Main.java b/chapter_4_thread_synchronization_part1/lecture_7_semaphores/src/main/java/Main.java new file mode 100644 index 0000000..82a86f2 --- /dev/null +++ b/chapter_4_thread_synchronization_part1/lecture_7_semaphores/src/main/java/Main.java @@ -0,0 +1,65 @@ +import java.util.concurrent.Semaphore; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +public class Main { + // similar to a lock but more complex + private static Semaphore semaphore = new Semaphore(2); + +// public static void main(String[] args) throws InterruptedException { +// // you can set negative permits which will require release to be called until >=1 is available +// Semaphore semaphore = new Semaphore(5); +// Lock lock = new ReentrantLock(); +// +// // only one thread can execute critical section +// lock.lock(); +// // critical section +// lock.unlock(); +// +// // multiple threads can execute critical section based on the permits allotted +// semaphore.acquire(); // lock +// // critical section +// semaphore.release(); // unlock +// } + + public static void main(String[] args) throws InterruptedException { + Executor executor = new Executor(); + + executor.submit(new Job(5000)); + executor.submit(new Job(10000)); + executor.submit(new Job(1000)); + } + + static class Executor { + public void submit(Job job) throws InterruptedException { + System.out.println("Launching job: " + job.getWork()); + semaphore.acquire(); + + Thread t = new Thread(() -> { + try { + System.out.println("Executing job: " + job.getWork()); + Thread.sleep(job.getWork()); + + semaphore.release(); + System.out.println("Job finished with id: " + job.getWork()); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }); + + t.start(); + } + } + + static class Job { + private final int work; + + public Job (int work) { + this.work = work; + } + + public int getWork() { + return work; + } + } +} diff --git a/chapter_5/lecture_3/src/main/java/Main.java b/chapter_5/lecture_3/src/main/java/Main.java deleted file mode 100644 index b032f71..0000000 --- a/chapter_5/lecture_3/src/main/java/Main.java +++ /dev/null @@ -1,48 +0,0 @@ -import java.util.concurrent.Phaser; - -public class Main { - - private static int S = 0; - private static int[] array = new int[] {1, 2, 3, 4, 5, 6, 7, 8}; - - private static Phaser phaser = new Phaser(1); - - public static void main(String[] args) { - for (int i = 0; i < array.length; i++) { - Thread t = new Thread(new WorkerThread(i)); - t.start(); - } - - phaser.arriveAndAwaitAdvance(); - phaser.arriveAndAwaitAdvance(); - - System.out.println("The sum is: " + S); - System.out.println("Phase count: " + phaser.getPhase()); - - } - - static class WorkerThread implements Runnable { - - private final int threadIndex; - - public WorkerThread(int threadIndex) { - this.threadIndex = threadIndex; - phaser.register(); - } - - @Override - public void run() { - array[threadIndex] = array[threadIndex] * 2; - phaser.arriveAndAwaitAdvance(); - - if (threadIndex == 0) { - for (int j : array) { - S = S + j; - } - phaser.arriveAndAwaitAdvance(); - } else { - phaser.arriveAndDeregister(); - } - } - } -} \ No newline at end of file diff --git a/chapter_5/lecture_4/src/main/java/Main.java b/chapter_5/lecture_4/src/main/java/Main.java deleted file mode 100644 index 369b61e..0000000 --- a/chapter_5/lecture_4/src/main/java/Main.java +++ /dev/null @@ -1,21 +0,0 @@ -import java.util.concurrent.Exchanger; - -public class Main { - public static void main(String[] args) throws InterruptedException { - Exchanger exchanger = new Exchanger<>(); - - Thread t = new Thread(() -> { - try { - String receivedValue = exchanger.exchange("value1"); - System.out.println("Received: " + receivedValue + " in thread " + Thread.currentThread().getName()); - } catch (InterruptedException e) { - e.printStackTrace(); - } - }); - - t.start(); - - String receivedValue = exchanger.exchange("value2"); - System.out.println("Received: " + receivedValue + " in thread " + Thread.currentThread().getName()); - } -} diff --git a/chapter_5/lecture_5/src/main/java/Main.java b/chapter_5/lecture_5/src/main/java/Main.java deleted file mode 100644 index 0b58631..0000000 --- a/chapter_5/lecture_5/src/main/java/Main.java +++ /dev/null @@ -1,35 +0,0 @@ -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -public class Main { - - private static Lock lock1 = new ReentrantLock(); - private static Lock lock2 = new ReentrantLock(); - - public static void main(String[] args) { - Thread t1 = new Thread(() -> { - lock2.tryLock(); - System.out.println("Thread 1 acquired lock2"); - - lock1.lock(); - System.out.println("Thread 1 acquired lock1"); - lock1.unlock(); - - lock2.unlock(); - }); - - Thread t2 = new Thread(() -> { - lock2.lock(); - System.out.println("Thread 2 acquired lock2"); - - lock1.lock(); - System.out.println("Thread 2 acquired lock1"); - lock1.unlock(); - - lock2.unlock(); - }); - - t1.start(); - t2.start(); - } -} diff --git a/chapter_5/lecture_6/src/main/java/Main.java b/chapter_5/lecture_6/src/main/java/Main.java deleted file mode 100644 index c0afb98..0000000 --- a/chapter_5/lecture_6/src/main/java/Main.java +++ /dev/null @@ -1,35 +0,0 @@ -public class Main { - - private static volatile int counter = 0; - - public static void main(String[] args) { - Thread t1 = new Thread(() -> { - int local_counter = counter; - - while (local_counter < 10) { - if (local_counter != counter) { - System.out.println("[T1] Local counter is changed "); - local_counter = counter; - } - } - }); - - Thread t2 = new Thread(() -> { - int local_counter = counter; - - while (local_counter < 10) { - System.out.println("[T2] Incremented counter to " + (local_counter + 1)); - counter = ++local_counter; - - try { - Thread.sleep(500); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - }); - - t1.start(); - t2.start(); - } -} diff --git a/chapter_5/lecture_1/build.gradle b/chapter_5_thread_synchronization_part2/lecture_1_count_down_latch/build.gradle similarity index 100% rename from chapter_5/lecture_1/build.gradle rename to chapter_5_thread_synchronization_part2/lecture_1_count_down_latch/build.gradle diff --git a/chapter_5/lecture_1/gradle/wrapper/gradle-wrapper.jar b/chapter_5_thread_synchronization_part2/lecture_1_count_down_latch/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_5/lecture_1/gradle/wrapper/gradle-wrapper.jar rename to chapter_5_thread_synchronization_part2/lecture_1_count_down_latch/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_5/lecture_1/gradle/wrapper/gradle-wrapper.properties b/chapter_5_thread_synchronization_part2/lecture_1_count_down_latch/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_5/lecture_1/gradle/wrapper/gradle-wrapper.properties rename to chapter_5_thread_synchronization_part2/lecture_1_count_down_latch/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_5/lecture_1/gradlew b/chapter_5_thread_synchronization_part2/lecture_1_count_down_latch/gradlew similarity index 100% rename from chapter_5/lecture_1/gradlew rename to chapter_5_thread_synchronization_part2/lecture_1_count_down_latch/gradlew diff --git a/chapter_5/lecture_1/gradlew.bat b/chapter_5_thread_synchronization_part2/lecture_1_count_down_latch/gradlew.bat similarity index 100% rename from chapter_5/lecture_1/gradlew.bat rename to chapter_5_thread_synchronization_part2/lecture_1_count_down_latch/gradlew.bat diff --git a/chapter_5/lecture_1/settings.gradle b/chapter_5_thread_synchronization_part2/lecture_1_count_down_latch/settings.gradle similarity index 100% rename from chapter_5/lecture_1/settings.gradle rename to chapter_5_thread_synchronization_part2/lecture_1_count_down_latch/settings.gradle diff --git a/chapter_5/lecture_1/src/main/java/Main.java b/chapter_5_thread_synchronization_part2/lecture_1_count_down_latch/src/main/java/Main.java similarity index 63% rename from chapter_5/lecture_1/src/main/java/Main.java rename to chapter_5_thread_synchronization_part2/lecture_1_count_down_latch/src/main/java/Main.java index fc1bc88..4ad23ab 100644 --- a/chapter_5/lecture_1/src/main/java/Main.java +++ b/chapter_5_thread_synchronization_part2/lecture_1_count_down_latch/src/main/java/Main.java @@ -1,25 +1,27 @@ import java.util.concurrent.CountDownLatch; public class Main { - private static int foundPosition = 0; private static int numberOfThreads = 2; - private static int numberToSearch = 8; + private static int numberToSearch = 9; private static int[] array = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 }; + private static CountDownLatch countDownLatch = new CountDownLatch(numberOfThreads); // one shot tool, once countdown reaches zero it will latch/lock - private static CountDownLatch countDownLatch = new CountDownLatch(numberOfThreads); - +// public static void main(String[] args) throws InterruptedException { +// CountDownLatch countDownLatch = new CountDownLatch(6); // one shot tool, once countdown reaches zero it will latch/lock +// countDownLatch.countDown(); // counts down from int provided above +// countDownLatch.await(); // waits until int above reaches zero +// } public static void main(String[] args) throws InterruptedException { int threadSlice = array.length / numberOfThreads; - for (int i = 0; i < numberOfThreads; i++) { + for (int i = 0; i < numberOfThreads; i++ ) { Thread t = new Thread(new WorkerThread(i * threadSlice, (i + 1) * threadSlice)); t.start(); } - countDownLatch.await(); - System.out.println("The number was found on position: " + foundPosition); + System.out.println("The number was found on position " + foundPosition); } static class WorkerThread implements Runnable { diff --git a/chapter_5/lecture_2/build.gradle b/chapter_5_thread_synchronization_part2/lecture_2_cyclic_barrier/build.gradle similarity index 100% rename from chapter_5/lecture_2/build.gradle rename to chapter_5_thread_synchronization_part2/lecture_2_cyclic_barrier/build.gradle diff --git a/chapter_5/lecture_2/gradle/wrapper/gradle-wrapper.jar b/chapter_5_thread_synchronization_part2/lecture_2_cyclic_barrier/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_5/lecture_2/gradle/wrapper/gradle-wrapper.jar rename to chapter_5_thread_synchronization_part2/lecture_2_cyclic_barrier/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_5/lecture_2/gradle/wrapper/gradle-wrapper.properties b/chapter_5_thread_synchronization_part2/lecture_2_cyclic_barrier/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_5/lecture_2/gradle/wrapper/gradle-wrapper.properties rename to chapter_5_thread_synchronization_part2/lecture_2_cyclic_barrier/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_5/lecture_2/gradlew b/chapter_5_thread_synchronization_part2/lecture_2_cyclic_barrier/gradlew similarity index 100% rename from chapter_5/lecture_2/gradlew rename to chapter_5_thread_synchronization_part2/lecture_2_cyclic_barrier/gradlew diff --git a/chapter_5/lecture_2/gradlew.bat b/chapter_5_thread_synchronization_part2/lecture_2_cyclic_barrier/gradlew.bat similarity index 100% rename from chapter_5/lecture_2/gradlew.bat rename to chapter_5_thread_synchronization_part2/lecture_2_cyclic_barrier/gradlew.bat diff --git a/chapter_5/lecture_2/settings.gradle b/chapter_5_thread_synchronization_part2/lecture_2_cyclic_barrier/settings.gradle similarity index 100% rename from chapter_5/lecture_2/settings.gradle rename to chapter_5_thread_synchronization_part2/lecture_2_cyclic_barrier/settings.gradle diff --git a/chapter_5/lecture_2/src/main/java/Main.java b/chapter_5_thread_synchronization_part2/lecture_2_cyclic_barrier/src/main/java/Main.java similarity index 67% rename from chapter_5/lecture_2/src/main/java/Main.java rename to chapter_5_thread_synchronization_part2/lecture_2_cyclic_barrier/src/main/java/Main.java index ee1743e..5293277 100644 --- a/chapter_5/lecture_2/src/main/java/Main.java +++ b/chapter_5_thread_synchronization_part2/lecture_2_cyclic_barrier/src/main/java/Main.java @@ -1,3 +1,4 @@ +import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -5,7 +6,14 @@ import java.util.concurrent.CyclicBarrier; public class Main { - +// public static void main(String[] args) throws InterruptedException, BrokenBarrierException { +// // barrier can be reused by new set of threads +// // parties - # of threads to wait for barrier +// // (optional) runnable to execute once all threads reached barrier, usually for clean up or initialization before threads proceed +// CyclicBarrier cyclicBarrier = new CyclicBarrier(4, () -> System.out.println("The barrier was released!")); +// +// cyclicBarrier.await(); // waits until required amount of threads have invoked await then they will be released +// } private static int[][] array = { {1, 2, 3, 1}, {2, 1, 2, 1}, @@ -36,16 +44,17 @@ public static void main(String[] args) throws InterruptedException { } System.out.println("The final array: " + Arrays.deepToString(array)); + System.out.println("Expected and Final Array are the same: " + (Arrays.deepToString(array).equals(Arrays.deepToString(outputArray)))); } static class WorkerThread implements Runnable { - private final int columnId; public WorkerThread(int columnId) { this.columnId = columnId; } + @Override public void run() { for (int i = 1; i < 4; i++) { @@ -60,7 +69,7 @@ public void run() { try { cyclicBarrier.await(); } catch (InterruptedException | BrokenBarrierException e) { - e.printStackTrace(); + throw new RuntimeException(e); } } } diff --git a/chapter_5/lecture_3/build.gradle b/chapter_5_thread_synchronization_part2/lecture_3_phaser/build.gradle similarity index 100% rename from chapter_5/lecture_3/build.gradle rename to chapter_5_thread_synchronization_part2/lecture_3_phaser/build.gradle diff --git a/chapter_5/lecture_3/gradle/wrapper/gradle-wrapper.jar b/chapter_5_thread_synchronization_part2/lecture_3_phaser/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_5/lecture_3/gradle/wrapper/gradle-wrapper.jar rename to chapter_5_thread_synchronization_part2/lecture_3_phaser/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_5/lecture_3/gradle/wrapper/gradle-wrapper.properties b/chapter_5_thread_synchronization_part2/lecture_3_phaser/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_5/lecture_3/gradle/wrapper/gradle-wrapper.properties rename to chapter_5_thread_synchronization_part2/lecture_3_phaser/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_5/lecture_3/gradlew b/chapter_5_thread_synchronization_part2/lecture_3_phaser/gradlew similarity index 100% rename from chapter_5/lecture_3/gradlew rename to chapter_5_thread_synchronization_part2/lecture_3_phaser/gradlew diff --git a/chapter_5/lecture_3/gradlew.bat b/chapter_5_thread_synchronization_part2/lecture_3_phaser/gradlew.bat similarity index 100% rename from chapter_5/lecture_3/gradlew.bat rename to chapter_5_thread_synchronization_part2/lecture_3_phaser/gradlew.bat diff --git a/chapter_5/lecture_3/settings.gradle b/chapter_5_thread_synchronization_part2/lecture_3_phaser/settings.gradle similarity index 100% rename from chapter_5/lecture_3/settings.gradle rename to chapter_5_thread_synchronization_part2/lecture_3_phaser/settings.gradle diff --git a/chapter_5_thread_synchronization_part2/lecture_3_phaser/src/main/java/Main.java b/chapter_5_thread_synchronization_part2/lecture_3_phaser/src/main/java/Main.java new file mode 100644 index 0000000..ebbc4c7 --- /dev/null +++ b/chapter_5_thread_synchronization_part2/lecture_3_phaser/src/main/java/Main.java @@ -0,0 +1,56 @@ +import java.util.concurrent.Phaser; + +public class Main { +// public static void main(String[] args) { +// // similar to cyclic barrier but more flexible +// Phaser phaser = new Phaser(3); +// +// phaser.register(); // threads can register themselves and increase counter +// phaser.arriveAndAwaitAdvance(); // similar to cyclic barrier "await()" +// phaser.getPhase(); // gets internal counter +// phaser.awaitAdvance(3); // takes phase ID to surpass that phase +// phaser.arriveAndDeregister(); // non-block and decrease counter +// } + + private static int S = 0; + private static final int[] array = new int[] {1, 2, 3, 4, 5, 6, 7, 8 }; + + private static final Phaser phaser = new Phaser(1); // 1 to account for the main thread + public static void main(String[] args) { + for (int i = 0; i < array.length; i++) { + new Thread(new WorkerThread(i)).start(); + } + + phaser.arriveAndAwaitAdvance(); // main thread + phaser.arriveAndAwaitAdvance(); // need to wait remainder thread from the custom threads + + System.out.println("The sum is: " + S); + System.out.println("Phase count: " + phaser.getPhase()); + } + + static class WorkerThread implements Runnable { + + private final int threadIndex; + + public WorkerThread(int threadIndex) { + this.threadIndex = threadIndex; + phaser.register(); + } + + @Override + public void run() { + array[threadIndex] = array[threadIndex] * 2; // double values in-place + phaser.arriveAndAwaitAdvance(); // threads wait here until all 8 have arrived here, once all here to next phase + + System.out.println("===> threadIndex: " + threadIndex); + if (threadIndex == 0) {// 1 thread reaches here while the rest deregister + for (int i : array) { + S = S + i; // sum doubled values + } + phaser.arriveAndAwaitAdvance(); // 1 thread + } else { + phaser.arriveAndDeregister(); + } + } + } +} \ No newline at end of file diff --git a/chapter_5/lecture_4/build.gradle b/chapter_5_thread_synchronization_part2/lecture_4_exchanger/build.gradle similarity index 100% rename from chapter_5/lecture_4/build.gradle rename to chapter_5_thread_synchronization_part2/lecture_4_exchanger/build.gradle diff --git a/chapter_5/lecture_4/gradle/wrapper/gradle-wrapper.jar b/chapter_5_thread_synchronization_part2/lecture_4_exchanger/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_5/lecture_4/gradle/wrapper/gradle-wrapper.jar rename to chapter_5_thread_synchronization_part2/lecture_4_exchanger/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_5/lecture_4/gradle/wrapper/gradle-wrapper.properties b/chapter_5_thread_synchronization_part2/lecture_4_exchanger/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_5/lecture_4/gradle/wrapper/gradle-wrapper.properties rename to chapter_5_thread_synchronization_part2/lecture_4_exchanger/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_5/lecture_4/gradlew b/chapter_5_thread_synchronization_part2/lecture_4_exchanger/gradlew similarity index 100% rename from chapter_5/lecture_4/gradlew rename to chapter_5_thread_synchronization_part2/lecture_4_exchanger/gradlew diff --git a/chapter_5/lecture_4/gradlew.bat b/chapter_5_thread_synchronization_part2/lecture_4_exchanger/gradlew.bat similarity index 100% rename from chapter_5/lecture_4/gradlew.bat rename to chapter_5_thread_synchronization_part2/lecture_4_exchanger/gradlew.bat diff --git a/chapter_5/lecture_4/settings.gradle b/chapter_5_thread_synchronization_part2/lecture_4_exchanger/settings.gradle similarity index 100% rename from chapter_5/lecture_4/settings.gradle rename to chapter_5_thread_synchronization_part2/lecture_4_exchanger/settings.gradle diff --git a/chapter_5_thread_synchronization_part2/lecture_4_exchanger/src/main/java/Main.java b/chapter_5_thread_synchronization_part2/lecture_4_exchanger/src/main/java/Main.java new file mode 100644 index 0000000..e820981 --- /dev/null +++ b/chapter_5_thread_synchronization_part2/lecture_4_exchanger/src/main/java/Main.java @@ -0,0 +1,33 @@ +import java.util.concurrent.Exchanger; + +public class Main { +// public static void main(String[] args) throws InterruptedException { +// // allows a pair of threads to exchange information - uneven pairs will be "stuck" and never execute +// Exchanger exchanger = new Exchanger<>(); +// +// // Thread 1 +// String receivedType1 = exchanger.exchange("value1"); +// +// // Thread 2 +// String receivedType2 = exchanger.exchange("value2"); +// } + + public static void main(String[] args) throws InterruptedException { + Exchanger exchanger = new Exchanger<>(); + + for (int i = 0; i < 3; i++) { + new Thread(() -> { + try { + String threadName = Thread.currentThread().getName(); + String receivedValue = exchanger.exchange("value_from_" + threadName); + System.out.println("Received: " + receivedValue + " in thread " + threadName); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + }).start(); + } + + String receivedValue = exchanger.exchange("value_from_main"); // main thread + System.out.println("Received: " + receivedValue + " in thread " + Thread.currentThread().getName()); + } +} diff --git a/chapter_5/lecture_5/build.gradle b/chapter_5_thread_synchronization_part2/lecture_5_deadlocks_and_livelocks/build.gradle similarity index 100% rename from chapter_5/lecture_5/build.gradle rename to chapter_5_thread_synchronization_part2/lecture_5_deadlocks_and_livelocks/build.gradle diff --git a/chapter_5/lecture_5/gradle/wrapper/gradle-wrapper.jar b/chapter_5_thread_synchronization_part2/lecture_5_deadlocks_and_livelocks/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_5/lecture_5/gradle/wrapper/gradle-wrapper.jar rename to chapter_5_thread_synchronization_part2/lecture_5_deadlocks_and_livelocks/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_5/lecture_5/gradle/wrapper/gradle-wrapper.properties b/chapter_5_thread_synchronization_part2/lecture_5_deadlocks_and_livelocks/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_5/lecture_5/gradle/wrapper/gradle-wrapper.properties rename to chapter_5_thread_synchronization_part2/lecture_5_deadlocks_and_livelocks/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_5/lecture_5/gradlew b/chapter_5_thread_synchronization_part2/lecture_5_deadlocks_and_livelocks/gradlew similarity index 100% rename from chapter_5/lecture_5/gradlew rename to chapter_5_thread_synchronization_part2/lecture_5_deadlocks_and_livelocks/gradlew diff --git a/chapter_5/lecture_5/gradlew.bat b/chapter_5_thread_synchronization_part2/lecture_5_deadlocks_and_livelocks/gradlew.bat similarity index 100% rename from chapter_5/lecture_5/gradlew.bat rename to chapter_5_thread_synchronization_part2/lecture_5_deadlocks_and_livelocks/gradlew.bat diff --git a/chapter_5/lecture_5/settings.gradle b/chapter_5_thread_synchronization_part2/lecture_5_deadlocks_and_livelocks/settings.gradle similarity index 100% rename from chapter_5/lecture_5/settings.gradle rename to chapter_5_thread_synchronization_part2/lecture_5_deadlocks_and_livelocks/settings.gradle diff --git a/chapter_5_thread_synchronization_part2/lecture_5_deadlocks_and_livelocks/src/main/java/Main.java b/chapter_5_thread_synchronization_part2/lecture_5_deadlocks_and_livelocks/src/main/java/Main.java new file mode 100644 index 0000000..3e84ec8 --- /dev/null +++ b/chapter_5_thread_synchronization_part2/lecture_5_deadlocks_and_livelocks/src/main/java/Main.java @@ -0,0 +1,44 @@ +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +public class Main { +// public static void main(String[] args) throws InterruptedException { +// Thread.currentThread().join(); // will not exit (ie deadlock) - best to use join w/ timeout +// } + private static Lock lock1 = new ReentrantLock(); + private static Lock lock2 = new ReentrantLock(); + + public static void main(String[] args) throws InterruptedException { + // acquires lock1, but lock2 is taken by thread 2 + Thread t1 = new Thread(() -> { + lock1.lock(); // tryLock() w/ specific timeout to interrupt deadlocks + System.out.println("Thread 1 acquired lock1"); + + lock2.lock(); + System.out.println("Thread 1 acquired lock2"); + lock2.unlock(); + + lock1.unlock(); + }); + + // acquires lock2, but lock1 is taken by thread 1 -> leads to deadlock since both threads are waiting for each other to release resources which keeps thread live and "stuck" + // `deadlocks` threads are blocked due to circular dependency + // can try to avoid with timeouts and process terminations + // if locks were set exactly as above -> no deadlock would be encountered + // `livelocks` threads are not able to make progress (not blocked) because they respond to each other but don't complete a task + // harder to detect because threads are active and consuming CPU resources + Thread t2 = new Thread(() -> { + lock2.lock(); + System.out.println("Thread 2 acquired lock2"); + + lock1.lock(); + System.out.println("Thread 2 acquired lock1"); + lock1.unlock(); + + lock2.unlock(); + }); + + t1.start(); + t2.start(); + } +} diff --git a/chapter_5/lecture_6/build.gradle b/chapter_5_thread_synchronization_part2/lecture_6_volatile/build.gradle similarity index 100% rename from chapter_5/lecture_6/build.gradle rename to chapter_5_thread_synchronization_part2/lecture_6_volatile/build.gradle diff --git a/chapter_5/lecture_6/gradle/wrapper/gradle-wrapper.jar b/chapter_5_thread_synchronization_part2/lecture_6_volatile/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_5/lecture_6/gradle/wrapper/gradle-wrapper.jar rename to chapter_5_thread_synchronization_part2/lecture_6_volatile/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_5/lecture_6/gradle/wrapper/gradle-wrapper.properties b/chapter_5_thread_synchronization_part2/lecture_6_volatile/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_5/lecture_6/gradle/wrapper/gradle-wrapper.properties rename to chapter_5_thread_synchronization_part2/lecture_6_volatile/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_5/lecture_6/gradlew b/chapter_5_thread_synchronization_part2/lecture_6_volatile/gradlew similarity index 100% rename from chapter_5/lecture_6/gradlew rename to chapter_5_thread_synchronization_part2/lecture_6_volatile/gradlew diff --git a/chapter_5/lecture_6/gradlew.bat b/chapter_5_thread_synchronization_part2/lecture_6_volatile/gradlew.bat similarity index 100% rename from chapter_5/lecture_6/gradlew.bat rename to chapter_5_thread_synchronization_part2/lecture_6_volatile/gradlew.bat diff --git a/chapter_5/lecture_6/settings.gradle b/chapter_5_thread_synchronization_part2/lecture_6_volatile/settings.gradle similarity index 100% rename from chapter_5/lecture_6/settings.gradle rename to chapter_5_thread_synchronization_part2/lecture_6_volatile/settings.gradle diff --git a/chapter_5_thread_synchronization_part2/lecture_6_volatile/src/main/java/Main.java b/chapter_5_thread_synchronization_part2/lecture_6_volatile/src/main/java/Main.java new file mode 100644 index 0000000..0624922 --- /dev/null +++ b/chapter_5_thread_synchronization_part2/lecture_6_volatile/src/main/java/Main.java @@ -0,0 +1,46 @@ +public class Main { + /** + * There is a delay between cache to update in main memory so in this scenario where + * private static int counter = 0; + * Thread1 will not see the update `counter` value and will get stuck in an infinity loop + * due to T1.localCounter never updating to what's in the main memory (RAM). + */ +// private static int counter = 0; + /** + * "volatile" keyword read's directly from the shared variable in the main memory + * to avoid stale data from the cached value + * Trade off: Increases consistency but decreases performance because cache look up is quicker + * than the main memory (RAM) + */ + private static volatile int counter = 0; + public static void main(String[] args) { + Thread t1 = new Thread(() -> { + int localCounter = counter; + + while (localCounter < 10) { + if (localCounter != counter) { + System.out.println("[T1] Local counter is changed " + localCounter); + localCounter = counter; + } + } + }); + + Thread t2 = new Thread(() -> { + int localCounter = counter; + + while (localCounter < 10) { + System.out.println("[T2] Incremented local counter to " + (localCounter + 1)); + counter = ++localCounter; + + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }); + + t1.start(); + t2.start(); + } +} diff --git a/chapter_5/project/build.gradle b/chapter_5_thread_synchronization_part2/project_simulating_mapreduce_with_threads/build.gradle similarity index 100% rename from chapter_5/project/build.gradle rename to chapter_5_thread_synchronization_part2/project_simulating_mapreduce_with_threads/build.gradle diff --git a/chapter_5/project/gradle/wrapper/gradle-wrapper.jar b/chapter_5_thread_synchronization_part2/project_simulating_mapreduce_with_threads/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_5/project/gradle/wrapper/gradle-wrapper.jar rename to chapter_5_thread_synchronization_part2/project_simulating_mapreduce_with_threads/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_5/project/gradle/wrapper/gradle-wrapper.properties b/chapter_5_thread_synchronization_part2/project_simulating_mapreduce_with_threads/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_5/project/gradle/wrapper/gradle-wrapper.properties rename to chapter_5_thread_synchronization_part2/project_simulating_mapreduce_with_threads/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_5/project/gradlew b/chapter_5_thread_synchronization_part2/project_simulating_mapreduce_with_threads/gradlew similarity index 100% rename from chapter_5/project/gradlew rename to chapter_5_thread_synchronization_part2/project_simulating_mapreduce_with_threads/gradlew diff --git a/chapter_5/project/gradlew.bat b/chapter_5_thread_synchronization_part2/project_simulating_mapreduce_with_threads/gradlew.bat similarity index 100% rename from chapter_5/project/gradlew.bat rename to chapter_5_thread_synchronization_part2/project_simulating_mapreduce_with_threads/gradlew.bat diff --git a/chapter_5/project/settings.gradle b/chapter_5_thread_synchronization_part2/project_simulating_mapreduce_with_threads/settings.gradle similarity index 100% rename from chapter_5/project/settings.gradle rename to chapter_5_thread_synchronization_part2/project_simulating_mapreduce_with_threads/settings.gradle diff --git a/chapter_5/project/src/main/java/Main.java b/chapter_5_thread_synchronization_part2/project_simulating_mapreduce_with_threads/src/main/java/Main.java similarity index 67% rename from chapter_5/project/src/main/java/Main.java rename to chapter_5_thread_synchronization_part2/project_simulating_mapreduce_with_threads/src/main/java/Main.java index f749c5b..5cfa07d 100644 --- a/chapter_5/project/src/main/java/Main.java +++ b/chapter_5_thread_synchronization_part2/project_simulating_mapreduce_with_threads/src/main/java/Main.java @@ -2,8 +2,10 @@ import java.util.concurrent.CountDownLatch; import java.util.stream.Collectors; +/** + * Simulating MapReduce with Threads + */ public class Main { - /* -> Intermediate result: @@ -30,36 +32,35 @@ public class Main { ], ... ] - - - */ - private static final String input = "a friend in need is a friend indeed"; - - private static final CountDownLatch countDownLatch = new CountDownLatch(2); - + private static final CountDownLatch countDownLatch = new CountDownLatch(2); // 2 counts == 2 Mapper threads private static final List> intermediateResult = Collections.synchronizedList(new ArrayList<>()); private static final List>> reducersInput = Collections.synchronizedList(new ArrayList<>()); public static void main(String[] args) throws InterruptedException { List inputList = Arrays.asList(input.split(" ")); - new Thread(new Mapper(inputList.subList(0, inputList.size() / 2))).start(); - new Thread(new Mapper(inputList.subList(inputList.size() / 2, inputList.size()))).start(); + // Map - map words in parallel between two threads and create "inputReducer" + int midListIdx = inputList.size() / 2; + new Thread(new Mapper(inputList.subList(0, midListIdx))).start(); + new Thread(new Mapper(inputList.subList(midListIdx, inputList.size()))).start(); + // Partition - filer unique words from inputReducer and re-order words group same words together Thread partitioner = new Thread(new Partitioner()); partitioner.start(); - partitioner.join(); + partitioner.join(); // makes sure the partitioner is complete before going to the Reducer - waits for the thread to die - for (List> reducerInput : reducersInput) { + // Reducer - count words in each group and print count of each word + for (List> reducerInput: reducersInput) { new Thread(new Reducer(reducerInput)).start(); } + +// System.out.println("Test"); // useful breakpoint to see values from `intermediateResult` and `reducersInput` } static class Mapper implements Runnable { private final List input; - public Mapper(List input) { this.input = input; } @@ -69,18 +70,19 @@ public void run() { for (String word : input) { intermediateResult.add(Map.entry(word, 1)); } + // guarantees that `Partitioner` thread won't start before `Mapper` threads are done countDownLatch.countDown(); } } static class Partitioner implements Runnable { - @Override public void run() { try { + // guarantees that `Partitioner` thread won't start before `Mapper` threads are done countDownLatch.await(); } catch (InterruptedException e) { - e.printStackTrace(); + throw new RuntimeException(e); } List uniqueWords = intermediateResult.stream() @@ -98,21 +100,19 @@ public void run() { } static class Reducer implements Runnable { - private final List> reducerInput; - public Reducer(List> reducerInput) { this.reducerInput = reducerInput; } @Override public void run() { - int S = 0; - for (Map.Entry entry: reducerInput) { - S += entry.getValue(); + int sum = 0; + for (Map.Entry entry : reducerInput) { + sum += entry.getValue(); } - System.out.println("The word: " + reducerInput.get(0).getKey() + " -> occurences: " + S); + System.out.println("The word: " + reducerInput.get(0).getKey() + " -> occurrences: " + sum); } } } diff --git a/chapter_6/lecture_2/src/main/java/Main.java b/chapter_6/lecture_2/src/main/java/Main.java deleted file mode 100644 index cba3d2f..0000000 --- a/chapter_6/lecture_2/src/main/java/Main.java +++ /dev/null @@ -1,38 +0,0 @@ -import java.util.concurrent.*; - -public class Main { - public static void main(String[] args) throws ExecutionException, InterruptedException { - ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( - 3, - 5, - 1, - TimeUnit.MINUTES, - new ArrayBlockingQueue<>(3) - ); - - threadPoolExecutor.prestartAllCoreThreads(); - - threadPoolExecutor.execute(() -> System.out.println("Task 1")); - threadPoolExecutor.execute(() -> System.out.println("Task 2")); - - System.out.println("Pool size: " + threadPoolExecutor.getPoolSize()); - - threadPoolExecutor.shutdown(); - threadPoolExecutor.awaitTermination(3, TimeUnit.SECONDS); - -// Future future = threadPoolExecutor.submit(new CallableTask()); -// -// // Do other stuff -// Integer result = future.get(); - - } - - static class CallableTask implements Callable { - - @Override - public Integer call() throws Exception { - // Do some work - return 4; - } - } -} diff --git a/chapter_6/lecture_5/src/main/java/Main.java b/chapter_6/lecture_5/src/main/java/Main.java deleted file mode 100644 index 0870b17..0000000 --- a/chapter_6/lecture_5/src/main/java/Main.java +++ /dev/null @@ -1,45 +0,0 @@ -import java.util.concurrent.*; - -public class Main { - public static void main(String[] args) { - ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( - 2, - 3, - 1, - TimeUnit.MINUTES, - new ArrayBlockingQueue<>(2), - new ThreadPoolExecutor.DiscardPolicy() - ); - - threadPoolExecutor.submit(new SleepingTask(1)); - threadPoolExecutor.submit(new SleepingTask(2)); - - System.out.println("[1] Pool size: " + threadPoolExecutor.getPoolSize()); - - threadPoolExecutor.submit(new SleepingTask(3)); - threadPoolExecutor.submit(new SleepingTask(4)); - - threadPoolExecutor.submit(new SleepingTask(5)); - System.out.println("[2] Pool size: " + threadPoolExecutor.getPoolSize()); - - threadPoolExecutor.submit(new SleepingTask(6)); - } - - static class SleepingTask implements Runnable { - - private final int id; - - public SleepingTask(int id) { - this.id = id; - } - - @Override - public void run() { - try { - Thread.sleep(99999); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } -} diff --git a/chapter_6/lecture_7/src/main/java/Main.java b/chapter_6/lecture_7/src/main/java/Main.java deleted file mode 100644 index e71d4f8..0000000 --- a/chapter_6/lecture_7/src/main/java/Main.java +++ /dev/null @@ -1,18 +0,0 @@ -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -public class Main { - public static void main(String[] args) { - ScheduledThreadPoolExecutor threadPoolExecutor = new ScheduledThreadPoolExecutor(3); - -// threadPoolExecutor.schedule(() -> System.out.println("Task"), 5, TimeUnit.SECONDS); - ScheduledFuture future = threadPoolExecutor.scheduleAtFixedRate(() -> System.out.println("Task"), 5, 1, TimeUnit.SECONDS); - - threadPoolExecutor.shutdown(); - threadPoolExecutor.shutdownNow(); - threadPoolExecutor.setExecuteExistingDelayedTasksAfterShutdownPolicy(true); - threadPoolExecutor.setContinueExistingPeriodicTasksAfterShutdownPolicy(true); - - } -} diff --git a/chapter_6/lecture_2/build.gradle b/chapter_6_thread_reusability/lecture_2_threadpools/build.gradle similarity index 100% rename from chapter_6/lecture_2/build.gradle rename to chapter_6_thread_reusability/lecture_2_threadpools/build.gradle diff --git a/chapter_6/lecture_2/gradle/wrapper/gradle-wrapper.jar b/chapter_6_thread_reusability/lecture_2_threadpools/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_6/lecture_2/gradle/wrapper/gradle-wrapper.jar rename to chapter_6_thread_reusability/lecture_2_threadpools/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_6/lecture_2/gradle/wrapper/gradle-wrapper.properties b/chapter_6_thread_reusability/lecture_2_threadpools/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_6/lecture_2/gradle/wrapper/gradle-wrapper.properties rename to chapter_6_thread_reusability/lecture_2_threadpools/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_6/lecture_2/gradlew b/chapter_6_thread_reusability/lecture_2_threadpools/gradlew similarity index 100% rename from chapter_6/lecture_2/gradlew rename to chapter_6_thread_reusability/lecture_2_threadpools/gradlew diff --git a/chapter_6/lecture_2/gradlew.bat b/chapter_6_thread_reusability/lecture_2_threadpools/gradlew.bat similarity index 100% rename from chapter_6/lecture_2/gradlew.bat rename to chapter_6_thread_reusability/lecture_2_threadpools/gradlew.bat diff --git a/chapter_6/lecture_2/settings.gradle b/chapter_6_thread_reusability/lecture_2_threadpools/settings.gradle similarity index 100% rename from chapter_6/lecture_2/settings.gradle rename to chapter_6_thread_reusability/lecture_2_threadpools/settings.gradle diff --git a/chapter_6_thread_reusability/lecture_2_threadpools/src/main/java/Main.java b/chapter_6_thread_reusability/lecture_2_threadpools/src/main/java/Main.java new file mode 100644 index 0000000..3269cca --- /dev/null +++ b/chapter_6_thread_reusability/lecture_2_threadpools/src/main/java/Main.java @@ -0,0 +1,119 @@ +import java.util.concurrent.*; + +public class Main { + public static void main(String[] args) throws ExecutionException, InterruptedException { + ThreadPoolExecutor threadPoolExecutor = new CustomThreadPoolExecuter( + 2, + 2, + 1, + TimeUnit.MINUTES, + new ArrayBlockingQueue<>(2) + // Types of Work Queues: + // bounded: new ArrayBlockingQueue<>(3) - has limited capacity and default access policy + // unbounded: new LinkedBlockingQueue<>() - not used often due to memory impact where queue can get full and lead to OOM + // synchronous: new SynchronousQueue<>() - has nonfair access policy therefore it doesn't store any tasks instead it hands-off tasks + ); +// // Lecture 4: Handling Exception +// // approach 1: within the task - best way since it's better to keep closer to the tasks, makes it easier for debugging +// threadPoolExecutor.submit(() -> { +// try { +// throw new RuntimeException(); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// }); +// // approach 2: as a future +// Future future = threadPoolExecutor.submit(() -> { +// throw new RuntimeException("test exception"); +// }); +// try { +// future.get(); +// } catch (InterruptedException | ExecutionException e) { +// e.printStackTrace(); +// } +// // approach 3: with custom executer - see CustomThreadPoolExecuter - not the best way but good to know since it can be in legacy code +// Future future = threadPoolExecutor.submit(() -> { +// throw new RuntimeException("test exception"); +// }); + +// // Lecture 3: Work Queues +// threadPoolExecutor.submit(() -> { +// try { +// Thread.sleep(3000); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } +// }); +// System.out.println("Task 1"); +// +// threadPoolExecutor.submit(() -> { +// try { +// Thread.sleep(3000); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } +// }); +// System.out.println("Task 2"); +// +// // Expected to be rejected since the thread limit is 2 +// threadPoolExecutor.submit(() -> { +// try { +// Thread.sleep(3000); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } +// }); +// System.out.println("Task 3"); + +// // Lecture 2: Getting familiarized with ThreadPoolExecutor +// threadPoolExecutor.prestartAllCoreThreads(); // creates all corePoolSize threads +// System.out.println("Pool size: " + threadPoolExecutor.getPoolSize()); + +// // Methods to close the application +// threadPoolExecutor.shutdown(); // graceful way to close thread pool by stop accepting new tasks into the queue and wait to complete existing tasks +//// threadPoolExecutor.shutdownNow(); // stops actively executing tasks and return tasks that were waiting in to be executed +// threadPoolExecutor.awaitTermination(3, TimeUnit.SECONDS); // blocks until all tasks have completed execution after a shutdown request, timeout occurs, or thread is interrupted - whichever happens first + + +// Future future = threadPoolExecutor.submit(new CallableTask()); // submits tasks to the ThreadPoolExecutor +// // Do other stuff +// Integer result = future.get(); // checks if result is available - if yes, returns result - if not, waits for results and then returns it + } + + //// approach 3: with custom executer + static class CustomThreadPoolExecuter extends ThreadPoolExecutor { + + public CustomThreadPoolExecuter(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue) { + super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); + } + + public CustomThreadPoolExecuter(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory) { + super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory); + } + + public CustomThreadPoolExecuter(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, RejectedExecutionHandler handler) { + super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler); + } + + public CustomThreadPoolExecuter(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { + super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler); + } + + @Override + protected void afterExecute(Runnable r, Throwable t) { + super.afterExecute(r, t); + + if (t != null) { + System.out.println("CustomThreadPoolExecuter.afterExecuter.t = " + t); + } + } + } + + static class CallableTask implements Callable { + @Override + public Integer call() throws Exception { + // Do some work + return 4; + } + } +} diff --git a/chapter_6/lecture_5/build.gradle b/chapter_6_thread_reusability/lecture_5_managing_rejected_and_monitoring_threads/build.gradle similarity index 100% rename from chapter_6/lecture_5/build.gradle rename to chapter_6_thread_reusability/lecture_5_managing_rejected_and_monitoring_threads/build.gradle diff --git a/chapter_6/lecture_5/gradle/wrapper/gradle-wrapper.jar b/chapter_6_thread_reusability/lecture_5_managing_rejected_and_monitoring_threads/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_6/lecture_5/gradle/wrapper/gradle-wrapper.jar rename to chapter_6_thread_reusability/lecture_5_managing_rejected_and_monitoring_threads/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_6/lecture_5/gradle/wrapper/gradle-wrapper.properties b/chapter_6_thread_reusability/lecture_5_managing_rejected_and_monitoring_threads/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_6/lecture_5/gradle/wrapper/gradle-wrapper.properties rename to chapter_6_thread_reusability/lecture_5_managing_rejected_and_monitoring_threads/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_6/lecture_5/gradlew b/chapter_6_thread_reusability/lecture_5_managing_rejected_and_monitoring_threads/gradlew similarity index 100% rename from chapter_6/lecture_5/gradlew rename to chapter_6_thread_reusability/lecture_5_managing_rejected_and_monitoring_threads/gradlew diff --git a/chapter_6/lecture_5/gradlew.bat b/chapter_6_thread_reusability/lecture_5_managing_rejected_and_monitoring_threads/gradlew.bat similarity index 100% rename from chapter_6/lecture_5/gradlew.bat rename to chapter_6_thread_reusability/lecture_5_managing_rejected_and_monitoring_threads/gradlew.bat diff --git a/chapter_6/lecture_5/settings.gradle b/chapter_6_thread_reusability/lecture_5_managing_rejected_and_monitoring_threads/settings.gradle similarity index 100% rename from chapter_6/lecture_5/settings.gradle rename to chapter_6_thread_reusability/lecture_5_managing_rejected_and_monitoring_threads/settings.gradle diff --git a/chapter_6_thread_reusability/lecture_5_managing_rejected_and_monitoring_threads/src/main/java/Main.java b/chapter_6_thread_reusability/lecture_5_managing_rejected_and_monitoring_threads/src/main/java/Main.java new file mode 100644 index 0000000..f5bada2 --- /dev/null +++ b/chapter_6_thread_reusability/lecture_5_managing_rejected_and_monitoring_threads/src/main/java/Main.java @@ -0,0 +1,62 @@ +import java.util.concurrent.*; + +public class Main { + // Lecture 5: Managing Rejected Tasks in ThreadPool - related to "RejectedExecutionHandler" + // Lecture 6: Monitoring the Performance of a ThreadPool - related to metrics + public static void main(String[] args) { + ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( + 2, + 3, + 1, + TimeUnit.MINUTES, + new ArrayBlockingQueue<>(2), + (Runnable r, ThreadPoolExecutor executer) -> { // if RejectedExecutionHandler used, the exception won't be thrown anymore + // push some metric to system + System.out.println("Task rejected"); + } +// new ThreadPoolExecutor.CallerRunsPolicy() // retry on the caller thread +// new ThreadPoolExecutor.DiscardOldestPolicy() // makes room in the queue for new task to be retried +// new ThreadPoolExecutor.DiscardPolicy() // does nothing - task will get discarded + ); +//// Lecture 6: Monitoring the Performance of a ThreadPool + threadPoolExecutor.getPoolSize(); // returns the number of threads currently used + threadPoolExecutor.getActiveCount(); // return number of threads are executing tasks + threadPoolExecutor.getTaskCount(); // correlates to the queue size + threadPoolExecutor.getCompletedTaskCount(); // calculate completed tasks + // should add metric to rejected tasks + + +//// Lecture 5: Managing Rejected Tasks in ThreadPool - related to "RejectedExecutionHandler" +// threadPoolExecutor.submit(new SleepingTask(1)); +// threadPoolExecutor.submit(new SleepingTask(2)); +// +// System.out.println("[1] Pool size: " + threadPoolExecutor.getPoolSize()); +// +// threadPoolExecutor.submit(new SleepingTask(3)); +// threadPoolExecutor.submit(new SleepingTask(4)); +// threadPoolExecutor.submit(new SleepingTask(5)); +// +// System.out.println("[2] Pool size: " + threadPoolExecutor.getPoolSize()); +// +// threadPoolExecutor.submit(new SleepingTask(6)); // expected to be rejected since the max pool size is 3 +// +// System.out.println("[3] Pool size: " + threadPoolExecutor.getPoolSize()); + } + + static class SleepingTask implements Runnable { + private final int id; + + public SleepingTask(int id) { + this.id = id; + } + + @Override + public void run() { + try { + Thread.sleep(99999); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } +} diff --git a/chapter_6/lecture_7/build.gradle b/chapter_6_thread_reusability/lecture_7_scheduled_threadpool_executor/build.gradle similarity index 100% rename from chapter_6/lecture_7/build.gradle rename to chapter_6_thread_reusability/lecture_7_scheduled_threadpool_executor/build.gradle diff --git a/chapter_6/lecture_7/gradle/wrapper/gradle-wrapper.jar b/chapter_6_thread_reusability/lecture_7_scheduled_threadpool_executor/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_6/lecture_7/gradle/wrapper/gradle-wrapper.jar rename to chapter_6_thread_reusability/lecture_7_scheduled_threadpool_executor/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_6/lecture_7/gradle/wrapper/gradle-wrapper.properties b/chapter_6_thread_reusability/lecture_7_scheduled_threadpool_executor/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_6/lecture_7/gradle/wrapper/gradle-wrapper.properties rename to chapter_6_thread_reusability/lecture_7_scheduled_threadpool_executor/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_6/lecture_7/gradlew b/chapter_6_thread_reusability/lecture_7_scheduled_threadpool_executor/gradlew similarity index 100% rename from chapter_6/lecture_7/gradlew rename to chapter_6_thread_reusability/lecture_7_scheduled_threadpool_executor/gradlew diff --git a/chapter_6/lecture_7/gradlew.bat b/chapter_6_thread_reusability/lecture_7_scheduled_threadpool_executor/gradlew.bat similarity index 100% rename from chapter_6/lecture_7/gradlew.bat rename to chapter_6_thread_reusability/lecture_7_scheduled_threadpool_executor/gradlew.bat diff --git a/chapter_6/lecture_7/settings.gradle b/chapter_6_thread_reusability/lecture_7_scheduled_threadpool_executor/settings.gradle similarity index 100% rename from chapter_6/lecture_7/settings.gradle rename to chapter_6_thread_reusability/lecture_7_scheduled_threadpool_executor/settings.gradle diff --git a/chapter_6_thread_reusability/lecture_7_scheduled_threadpool_executor/src/main/java/Main.java b/chapter_6_thread_reusability/lecture_7_scheduled_threadpool_executor/src/main/java/Main.java new file mode 100644 index 0000000..72e6a0a --- /dev/null +++ b/chapter_6_thread_reusability/lecture_7_scheduled_threadpool_executor/src/main/java/Main.java @@ -0,0 +1,21 @@ +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class Main { + public static void main(String[] args) { + // Extends ThreadPoolExecutor which can be schedule + // starts with an initial capacity but can increase if it needs more - it could reach OOM + ScheduledThreadPoolExecutor threadPoolExecutor = new ScheduledThreadPoolExecutor(3); + +// threadPoolExecutor.schedule(() -> System.out.println("Task"), 5, TimeUnit.SECONDS); +// ScheduledFuture future = threadPoolExecutor.scheduleAtFixedRate(() -> System.out.println("Task"), 5, 1, TimeUnit.SECONDS); // initial delay then it executes at every period - good if you need to schedule task such as polling or pushing metrics/job +// threadPoolExecutor.setRemoveOnCancelPolicy(true); // will remove cancelled tasks from the queue +// future.cancel(true); // cancelled task are not removed from queue and will remain taking up memory + threadPoolExecutor.shutdown(); // graceful shutdown + threadPoolExecutor.shutdownNow(); // forces shutdown quickly + threadPoolExecutor.setExecuteExistingDelayedTasksAfterShutdownPolicy(true); // currently delays tasks will be executed even after shutdown + threadPoolExecutor.setContinueExistingPeriodicTasksAfterShutdownPolicy(true); // similar to above but to be used with "scheduleAtFixedRate" + + } +} diff --git a/chapter_6/lecture_8/build.gradle b/chapter_6_thread_reusability/lecture_8_fork_join_pool/build.gradle similarity index 100% rename from chapter_6/lecture_8/build.gradle rename to chapter_6_thread_reusability/lecture_8_fork_join_pool/build.gradle diff --git a/chapter_6/lecture_8/gradle/wrapper/gradle-wrapper.jar b/chapter_6_thread_reusability/lecture_8_fork_join_pool/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_6/lecture_8/gradle/wrapper/gradle-wrapper.jar rename to chapter_6_thread_reusability/lecture_8_fork_join_pool/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_6/lecture_8/gradle/wrapper/gradle-wrapper.properties b/chapter_6_thread_reusability/lecture_8_fork_join_pool/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_6/lecture_8/gradle/wrapper/gradle-wrapper.properties rename to chapter_6_thread_reusability/lecture_8_fork_join_pool/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_6/lecture_8/gradlew b/chapter_6_thread_reusability/lecture_8_fork_join_pool/gradlew similarity index 100% rename from chapter_6/lecture_8/gradlew rename to chapter_6_thread_reusability/lecture_8_fork_join_pool/gradlew diff --git a/chapter_6/lecture_8/gradlew.bat b/chapter_6_thread_reusability/lecture_8_fork_join_pool/gradlew.bat similarity index 100% rename from chapter_6/lecture_8/gradlew.bat rename to chapter_6_thread_reusability/lecture_8_fork_join_pool/gradlew.bat diff --git a/chapter_6/lecture_8/settings.gradle b/chapter_6_thread_reusability/lecture_8_fork_join_pool/settings.gradle similarity index 100% rename from chapter_6/lecture_8/settings.gradle rename to chapter_6_thread_reusability/lecture_8_fork_join_pool/settings.gradle diff --git a/chapter_6/lecture_8/src/main/java/Main.java b/chapter_6_thread_reusability/lecture_8_fork_join_pool/src/main/java/Main.java similarity index 60% rename from chapter_6/lecture_8/src/main/java/Main.java rename to chapter_6_thread_reusability/lecture_8_fork_join_pool/src/main/java/Main.java index 82ee8fe..adecd4e 100644 --- a/chapter_6/lecture_8/src/main/java/Main.java +++ b/chapter_6_thread_reusability/lecture_8_fork_join_pool/src/main/java/Main.java @@ -6,9 +6,13 @@ public class Main { private static int[] array = new int[] {1, 2, 3, 4, 5, 6, 7, 8}; public static void main(String[] args) throws ExecutionException, InterruptedException { - ForkJoinPool pool = new ForkJoinPool(2); - - Future future = pool.submit(new IncrementTask(0, 8)); + // Useful for "divide and conquer" problems or tasks that can be executed in parallel + // it allows work stealing where idle threads can steal work from busy ones to maximize efficiency + // Creates threads based on available CPU + ForkJoinPool pool = new ForkJoinPool(2); // very hungry threads, if no work, it'll find it +// pool.getStealCount(); // threads can steal work from each other + Future future = pool.submit(new IncrementTask(0, 8)); // same as ThreadPoolExecutor +// pool.execute(); // same as ThreadPoolExecutor future.get(); @@ -27,12 +31,12 @@ public IncrementTask(int left, int right) { @Override protected void compute() { if (right - left < 3) { - for (int i = left; i < right; i++) { + for (int i = left; i < right; i ++ ) { array[i]++; } } else { int mid = (left + right) / 2; - invokeAll(new IncrementTask(left, mid), new IncrementTask(mid, right)); + invokeAll(new IncrementTask(left, mid), new IncrementTask(mid, right)); // will execute tasks in parallel } } } diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/executionHistory/executionHistory.bin b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/executionHistory/executionHistory.bin new file mode 100644 index 0000000..bc38468 Binary files /dev/null and b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/executionHistory/executionHistory.bin differ diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/executionHistory/executionHistory.lock b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/executionHistory/executionHistory.lock new file mode 100644 index 0000000..853a30e Binary files /dev/null and b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/executionHistory/executionHistory.lock differ diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/fileChanges/last-build.bin b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/fileChanges/last-build.bin new file mode 100644 index 0000000..f76dd23 Binary files /dev/null and b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/fileChanges/last-build.bin differ diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/fileContent/fileContent.lock b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/fileContent/fileContent.lock new file mode 100644 index 0000000..c8538c6 Binary files /dev/null and b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/fileContent/fileContent.lock differ diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/fileHashes/fileHashes.bin b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/fileHashes/fileHashes.bin new file mode 100644 index 0000000..7fdf4fb Binary files /dev/null and b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/fileHashes/fileHashes.bin differ diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/fileHashes/fileHashes.lock b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/fileHashes/fileHashes.lock new file mode 100644 index 0000000..4a48054 Binary files /dev/null and b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/fileHashes/fileHashes.lock differ diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/gc.properties b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/gc.properties new file mode 100644 index 0000000..e69de29 diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/javaCompile/classAnalysis.bin b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/javaCompile/classAnalysis.bin new file mode 100644 index 0000000..a65113d Binary files /dev/null and b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/javaCompile/classAnalysis.bin differ diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/javaCompile/javaCompile.lock b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/javaCompile/javaCompile.lock new file mode 100644 index 0000000..28d8228 Binary files /dev/null and b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/javaCompile/javaCompile.lock differ diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/javaCompile/taskHistory.bin b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/javaCompile/taskHistory.bin new file mode 100644 index 0000000..f62e519 Binary files /dev/null and b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/6.3/javaCompile/taskHistory.bin differ diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/buildOutputCleanup/buildOutputCleanup.lock new file mode 100644 index 0000000..5ba6746 Binary files /dev/null and b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/buildOutputCleanup/cache.properties b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/buildOutputCleanup/cache.properties new file mode 100644 index 0000000..daa898d --- /dev/null +++ b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/buildOutputCleanup/cache.properties @@ -0,0 +1,2 @@ +#Sun Jul 07 14:49:54 PDT 2024 +gradle.version=6.3 diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/buildOutputCleanup/outputFiles.bin b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/buildOutputCleanup/outputFiles.bin new file mode 100644 index 0000000..3298420 Binary files /dev/null and b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/buildOutputCleanup/outputFiles.bin differ diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/checksums/checksums.lock b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/checksums/checksums.lock new file mode 100644 index 0000000..5ec1ace Binary files /dev/null and b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/checksums/checksums.lock differ diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/vcs-1/gc.properties b/chapter_6_thread_reusability/lecture_9_executors_class/.gradle/vcs-1/gc.properties new file mode 100644 index 0000000..e69de29 diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/.idea/.gitignore b/chapter_6_thread_reusability/lecture_9_executors_class/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/chapter_6_thread_reusability/lecture_9_executors_class/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/.idea/.name b/chapter_6_thread_reusability/lecture_9_executors_class/.idea/.name new file mode 100644 index 0000000..fdc1fed --- /dev/null +++ b/chapter_6_thread_reusability/lecture_9_executors_class/.idea/.name @@ -0,0 +1 @@ +executor \ No newline at end of file diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/.idea/codeStyles/Project.xml b/chapter_6_thread_reusability/lecture_9_executors_class/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..919ce1f --- /dev/null +++ b/chapter_6_thread_reusability/lecture_9_executors_class/.idea/codeStyles/Project.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/.idea/codeStyles/codeStyleConfig.xml b/chapter_6_thread_reusability/lecture_9_executors_class/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..a55e7a1 --- /dev/null +++ b/chapter_6_thread_reusability/lecture_9_executors_class/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/.idea/compiler.xml b/chapter_6_thread_reusability/lecture_9_executors_class/.idea/compiler.xml new file mode 100644 index 0000000..fb7f4a8 --- /dev/null +++ b/chapter_6_thread_reusability/lecture_9_executors_class/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/.idea/gradle.xml b/chapter_6_thread_reusability/lecture_9_executors_class/.idea/gradle.xml new file mode 100644 index 0000000..7d3b3e8 --- /dev/null +++ b/chapter_6_thread_reusability/lecture_9_executors_class/.idea/gradle.xml @@ -0,0 +1,17 @@ + + + + + + + \ No newline at end of file diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/.idea/jarRepositories.xml b/chapter_6_thread_reusability/lecture_9_executors_class/.idea/jarRepositories.xml new file mode 100644 index 0000000..fdc392f --- /dev/null +++ b/chapter_6_thread_reusability/lecture_9_executors_class/.idea/jarRepositories.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/.idea/misc.xml b/chapter_6_thread_reusability/lecture_9_executors_class/.idea/misc.xml new file mode 100644 index 0000000..c3df9b0 --- /dev/null +++ b/chapter_6_thread_reusability/lecture_9_executors_class/.idea/misc.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/.idea/vcs.xml b/chapter_6_thread_reusability/lecture_9_executors_class/.idea/vcs.xml new file mode 100644 index 0000000..b2bdec2 --- /dev/null +++ b/chapter_6_thread_reusability/lecture_9_executors_class/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/chapter_7/lecture_1/build.gradle b/chapter_6_thread_reusability/lecture_9_executors_class/build.gradle similarity index 100% rename from chapter_7/lecture_1/build.gradle rename to chapter_6_thread_reusability/lecture_9_executors_class/build.gradle diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/build/classes/java/main/Main.class b/chapter_6_thread_reusability/lecture_9_executors_class/build/classes/java/main/Main.class new file mode 100644 index 0000000..d6ab259 Binary files /dev/null and b/chapter_6_thread_reusability/lecture_9_executors_class/build/classes/java/main/Main.class differ diff --git a/chapter_7/lecture_1/gradle/wrapper/gradle-wrapper.jar b/chapter_6_thread_reusability/lecture_9_executors_class/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_7/lecture_1/gradle/wrapper/gradle-wrapper.jar rename to chapter_6_thread_reusability/lecture_9_executors_class/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_7/lecture_1/gradle/wrapper/gradle-wrapper.properties b/chapter_6_thread_reusability/lecture_9_executors_class/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_7/lecture_1/gradle/wrapper/gradle-wrapper.properties rename to chapter_6_thread_reusability/lecture_9_executors_class/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_7/lecture_1/gradlew b/chapter_6_thread_reusability/lecture_9_executors_class/gradlew similarity index 100% rename from chapter_7/lecture_1/gradlew rename to chapter_6_thread_reusability/lecture_9_executors_class/gradlew diff --git a/chapter_7/lecture_1/gradlew.bat b/chapter_6_thread_reusability/lecture_9_executors_class/gradlew.bat similarity index 100% rename from chapter_7/lecture_1/gradlew.bat rename to chapter_6_thread_reusability/lecture_9_executors_class/gradlew.bat diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/settings.gradle b/chapter_6_thread_reusability/lecture_9_executors_class/settings.gradle new file mode 100644 index 0000000..ddfd7d2 --- /dev/null +++ b/chapter_6_thread_reusability/lecture_9_executors_class/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = 'executor' + diff --git a/chapter_6_thread_reusability/lecture_9_executors_class/src/main/java/Main.java b/chapter_6_thread_reusability/lecture_9_executors_class/src/main/java/Main.java new file mode 100644 index 0000000..25b2f4d --- /dev/null +++ b/chapter_6_thread_reusability/lecture_9_executors_class/src/main/java/Main.java @@ -0,0 +1,29 @@ +import java.util.Arrays; +import java.util.concurrent.*; + +public class Main { + // Executors - utility class that allows threads to be created with 1 line of code + // captures common thread creations + public static void main(String[] args) { + // a lot of the thread pools done in previous lectures are available in the "Executors" utility class + ExecutorService executorService = Executors.newFixedThreadPool(5); // creates instance with unbounded queue (non-resizable), uses "LinkedBlockingQueue" + ExecutorService executorService1 = Executors.newCachedThreadPool(new MyThreadFactory()); // handoff mechanism, if no worker available it will create new threads up to max value (~2 billion), uses "SynchronousQueue" + ExecutorService executorService2 = Executors.newWorkStealingPool(); // work stealing pool, uses "ForkJoinPool" + ExecutorService executorService3 = Executors.newSingleThreadExecutor(); + ExecutorService executorService4 = Executors.newSingleThreadScheduledExecutor(); + } + + static class MyThreadFactory implements ThreadFactory { + + @Override + public Thread newThread(Runnable r) { + Thread t = new Thread(r); + + t.setPriority(4); + t.setName("my-thread"); + + return t; + } + } + +} diff --git a/chapter_7/lecture_2/build.gradle b/chapter_7/lecture_1_parallel_quick_sort_threads/build.gradle similarity index 100% rename from chapter_7/lecture_2/build.gradle rename to chapter_7/lecture_1_parallel_quick_sort_threads/build.gradle diff --git a/chapter_7/lecture_2/gradle/wrapper/gradle-wrapper.jar b/chapter_7/lecture_1_parallel_quick_sort_threads/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_7/lecture_2/gradle/wrapper/gradle-wrapper.jar rename to chapter_7/lecture_1_parallel_quick_sort_threads/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_7/lecture_2/gradle/wrapper/gradle-wrapper.properties b/chapter_7/lecture_1_parallel_quick_sort_threads/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_7/lecture_2/gradle/wrapper/gradle-wrapper.properties rename to chapter_7/lecture_1_parallel_quick_sort_threads/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_7/lecture_2/gradlew b/chapter_7/lecture_1_parallel_quick_sort_threads/gradlew similarity index 100% rename from chapter_7/lecture_2/gradlew rename to chapter_7/lecture_1_parallel_quick_sort_threads/gradlew diff --git a/chapter_7/lecture_2/gradlew.bat b/chapter_7/lecture_1_parallel_quick_sort_threads/gradlew.bat similarity index 100% rename from chapter_7/lecture_2/gradlew.bat rename to chapter_7/lecture_1_parallel_quick_sort_threads/gradlew.bat diff --git a/chapter_7/lecture_1/settings.gradle b/chapter_7/lecture_1_parallel_quick_sort_threads/settings.gradle similarity index 100% rename from chapter_7/lecture_1/settings.gradle rename to chapter_7/lecture_1_parallel_quick_sort_threads/settings.gradle diff --git a/chapter_7/lecture_1/src/main/java/Main.java b/chapter_7/lecture_1_parallel_quick_sort_threads/src/main/java/Main.java similarity index 67% rename from chapter_7/lecture_1/src/main/java/Main.java rename to chapter_7/lecture_1_parallel_quick_sort_threads/src/main/java/Main.java index 4b7862e..f4f39a9 100644 --- a/chapter_7/lecture_1/src/main/java/Main.java +++ b/chapter_7/lecture_1_parallel_quick_sort_threads/src/main/java/Main.java @@ -1,5 +1,7 @@ import java.util.Random; import java.util.concurrent.ExecutionException; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinTask; import java.util.concurrent.RecursiveAction; public class Main { @@ -8,20 +10,6 @@ public class Main { private static int arraySize = 100000000; private static int[] array = new int[arraySize]; - // Fork Join - // Run 1 -> 5.814 seconds - // Run 2 -> 5.504 seconds - // Run 3 -> 5.758 seconds - // Run 4 -> 6.038 seconds - // Run 5 -> 5.495 seconds - - // Classical recursive - // Run 1 -> 10.87 seconds - // Run 2 -> 10.94 seconds - // Run 3 -> 10.77 seconds - // Run 4 -> 10.83 seconds - // Run 5 -> 10.80 seconds - public static void main(String[] args) throws ExecutionException, InterruptedException { for (int i = 0; i < arraySize; i++) { array[i] = random.nextInt(arraySize); @@ -29,28 +17,33 @@ public static void main(String[] args) throws ExecutionException, InterruptedExc // System.out.println(Arrays.toString(array)); - - long start = System.nanoTime(); quickSort(0, arraySize - 1); + // Classical recursive execution + // Run 1 -> 13.223 seconds + // Run 2 -> 12.260 seconds + // Run 3 -> 12.364 seconds + // Run 4 -> 14.279 seconds + // Run 5 -> 12.459 seconds // ForkJoinPool forkJoinPool = new ForkJoinPool(); // ForkJoinTask future = forkJoinPool.submit(new QuickSortTask(0, arraySize - 1)); -// // future.get(); + // Fork Join execution + // Run 1 -> 3.151 seconds + // Run 2 -> 2.857 seconds + // Run 3 -> 2.858 seconds + // Run 4 -> 2.768 seconds + // Run 5 -> 3.509 seconds long end = System.nanoTime(); System.out.println("Execution time = " + (end - start)); - - // System.out.println(Arrays.toString(array)); - } static class QuickSortTask extends RecursiveAction { - private final int left; private final int right; @@ -63,18 +56,34 @@ public QuickSortTask(int left, int right) { protected void compute() { if (left < right) { int pivotIndex = partition(left, right); - invokeAll(new QuickSortTask(left, pivotIndex - 1), - new QuickSortTask(pivotIndex + 1, right)); + + // Fork Join +// invokeAll(new QuickSortTask(left, pivotIndex - 1), +// new QuickSortTask(pivotIndex + 1, right)); + + // Classical recursive + quickSort(left, pivotIndex - 1); + quickSort(pivotIndex + 1, right); } } + + } + + static void quickSort(int left, int right) { + if (left < right) { + int pivotIndex = partition(left, right); + + quickSort(left, pivotIndex - 1); + quickSort(pivotIndex + 1, right); + } } static int partition(int left, int right) { int pivot = array[right]; int swapIndex = left - 1; - for (int i = left; i < right; i++) { - if(array[i] < pivot) { + for (int i = left; i < right; i ++) { + if (array[i] < pivot) { swapIndex++; swap(swapIndex, i); } @@ -82,22 +91,13 @@ static int partition(int left, int right) { swapIndex++; swap(swapIndex, right); - return swapIndex; } - static void quickSort(int left, int right) { - if (left < right) { - int pivotIndex = partition(left, right); - - quickSort(left, pivotIndex - 1); - quickSort(pivotIndex + 1, right); - } - } - static void swap(int leftIndex, int rightIndex) { - int aux = array[leftIndex]; + int temp = array[leftIndex]; array[leftIndex] = array[rightIndex]; - array[rightIndex] = aux; + array[rightIndex] = temp; } + } \ No newline at end of file diff --git a/chapter_7/lecture_2/settings.gradle b/chapter_7/lecture_2/settings.gradle deleted file mode 100644 index 6aae90d..0000000 --- a/chapter_7/lecture_2/settings.gradle +++ /dev/null @@ -1,2 +0,0 @@ -rootProject.name = 'parallel-merge-sort' - diff --git a/chapter_7/lecture_3/build.gradle b/chapter_7/lecture_2_binary_search_cannot_parallel/build.gradle similarity index 100% rename from chapter_7/lecture_3/build.gradle rename to chapter_7/lecture_2_binary_search_cannot_parallel/build.gradle diff --git a/chapter_7/lecture_3/gradle/wrapper/gradle-wrapper.jar b/chapter_7/lecture_2_binary_search_cannot_parallel/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from chapter_7/lecture_3/gradle/wrapper/gradle-wrapper.jar rename to chapter_7/lecture_2_binary_search_cannot_parallel/gradle/wrapper/gradle-wrapper.jar diff --git a/chapter_7/lecture_3/gradle/wrapper/gradle-wrapper.properties b/chapter_7/lecture_2_binary_search_cannot_parallel/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from chapter_7/lecture_3/gradle/wrapper/gradle-wrapper.properties rename to chapter_7/lecture_2_binary_search_cannot_parallel/gradle/wrapper/gradle-wrapper.properties diff --git a/chapter_7/lecture_3/gradlew b/chapter_7/lecture_2_binary_search_cannot_parallel/gradlew similarity index 100% rename from chapter_7/lecture_3/gradlew rename to chapter_7/lecture_2_binary_search_cannot_parallel/gradlew diff --git a/chapter_7/lecture_3/gradlew.bat b/chapter_7/lecture_2_binary_search_cannot_parallel/gradlew.bat similarity index 100% rename from chapter_7/lecture_3/gradlew.bat rename to chapter_7/lecture_2_binary_search_cannot_parallel/gradlew.bat diff --git a/chapter_7/lecture_2_binary_search_cannot_parallel/settings.gradle b/chapter_7/lecture_2_binary_search_cannot_parallel/settings.gradle new file mode 100644 index 0000000..e94d8f0 --- /dev/null +++ b/chapter_7/lecture_2_binary_search_cannot_parallel/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = 'binary-search-cannot-parallel' + diff --git a/chapter_7/lecture_2/src/main/java/Main.java b/chapter_7/lecture_2_binary_search_cannot_parallel/src/main/java/Main.java similarity index 73% rename from chapter_7/lecture_2/src/main/java/Main.java rename to chapter_7/lecture_2_binary_search_cannot_parallel/src/main/java/Main.java index b055d6d..6cb861e 100644 --- a/chapter_7/lecture_2/src/main/java/Main.java +++ b/chapter_7/lecture_2_binary_search_cannot_parallel/src/main/java/Main.java @@ -1,6 +1,13 @@ import java.util.Arrays; public class Main { + /* + Binary search cannot be efficiently parallelized. + + Not everything benefits from parallelization. A deep dive is needed to determine its effectiveness. + For example, in Binary Search, splitting work across threads can be inefficient, + as some threads may return no results. + */ private static int arraySize = 20; private static int numberToSearch = 5; diff --git a/chapter_7/lecture_3/src/main/java/Main.java b/chapter_7/lecture_3/src/main/java/Main.java deleted file mode 100644 index b3efdaf..0000000 --- a/chapter_7/lecture_3/src/main/java/Main.java +++ /dev/null @@ -1,227 +0,0 @@ -import java.util.Random; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Semaphore; -import java.util.concurrent.TimeUnit; - -public class Main { - private static final int N = 2000; - - private static final Random random = new Random(); - - private static final int[][] A = new int[N][N]; - private static final int[][] B = new int[N][N]; - private static final int[][] C = new int[N][N]; - - // Matrix multiplication results - private static final int[][] result1 = new int[N / 2][N / 2]; - private static final int[][] result2 = new int[N / 2][N / 2]; - private static final int[][] result3 = new int[N / 2][N / 2]; - private static final int[][] result4 = new int[N / 2][N / 2]; - private static final int[][] result5 = new int[N / 2][N / 2]; - private static final int[][] result6 = new int[N / 2][N / 2]; - private static final int[][] result7 = new int[N / 2][N / 2]; - private static final int[][] result8 = new int[N / 2][N / 2]; - - // 1. How many task types do we need to have? -> 2 tasks -> multiplication, a sum - task - // 2. How can we identify the blocks that we need to multiply? - // 3. How can we write the blocks in the output array? - - - // Serial, 2K x 2K - // Run 1 -> 54.48 seconds - // Run 2 -> 54.15 seconds - // Run 3 -> 53.80 seconds - - // Block parallel, 2K x 2K (4 threads) - // Run 1 -> 23.81 seconds - // Run 2 -> 24.20 seconds - // Run 3 -> 25.16 seconds - - - public static void main(String[] args) throws InterruptedException { - initMatrixes(); - -// printMatrix(A); -// printMatrix(B); - - long start = System.nanoTime(); - multiplyParallelPerBlock(); -// multiplySerial(); - long end = System.nanoTime(); - - System.out.println("Execution time = " + (end - start)); - - checkResult(); - -// printMatrix(C); - } - - static void multiplyParallelPerBlock() throws InterruptedException { - ExecutorService executorService = Executors.newFixedThreadPool(8); - - Semaphore semaphore1 = new Semaphore(0); - Semaphore semaphore2 = new Semaphore(0); - Semaphore semaphore3 = new Semaphore(0); - Semaphore semaphore4 = new Semaphore(0); - - // This computes upper-left quadrant - executorService.submit(new BlockMultiplyTask(0, 0, 0, result1, semaphore1)); - executorService.submit(new BlockMultiplyTask(0, 0, N / 2, result2, semaphore1)); - executorService.submit(new SumTask(0, 0, result1, result2, semaphore1)); - - // This computes upper-right quadrant - executorService.submit(new BlockMultiplyTask(0, N / 2, 0, result3, semaphore2)); - executorService.submit(new BlockMultiplyTask(0, N / 2, N / 2, result4, semaphore2)); - executorService.submit(new SumTask(0, N / 2, result3, result4, semaphore2)); - - // This computes bottom-left quadrant - executorService.submit(new BlockMultiplyTask(N / 2, 0, 0, result5, semaphore3)); - executorService.submit(new BlockMultiplyTask(N / 2, 0, N / 2, result6, semaphore3)); - executorService.submit(new SumTask(N / 2, 0, result5, result6, semaphore3)); - - // This computes bottom-right quadrant - executorService.submit(new BlockMultiplyTask(N / 2, N / 2, 0, result7, semaphore4)); - executorService.submit(new BlockMultiplyTask(N / 2, N / 2, N / 2, result8, semaphore4)); - executorService.submit(new SumTask(N / 2, N / 2, result7, result8, semaphore4)); - - executorService.shutdown(); - executorService.awaitTermination(1, TimeUnit.MINUTES); - } - - static class BlockMultiplyTask implements Runnable { - private final int lineStart; - private final int colStart; - private final int blockStart; - private final int[][] result; - private final Semaphore semaphore; - - public BlockMultiplyTask(int lineStart, int colStart, int blockStart, int[][] result, Semaphore semaphore) { - this.lineStart = lineStart; - this.colStart = colStart; - this.blockStart = blockStart; - - this.result = result; - this.semaphore = semaphore; - } - - @Override - public void run() { - for (int i = lineStart, resultX = 0; i < lineStart + N / 2; i++, resultX++) { - for (int j = colStart, resultY = 0; j < colStart + N / 2; j++, resultY++) { - - result[resultX][resultY] = 0; - - for (int k = blockStart; k < blockStart + N / 2; k++) { - result[resultX][resultY] += A[i][k] * B[k][j]; - } - } - } - semaphore.release(); - } - } - - static class SumTask implements Runnable { - private final int lineStart; - private final int colStart; - private final int[][] resultA; - private final int[][] resultB; - private final Semaphore semaphore; - - public SumTask(int lineStart, int colStart, int[][] resultA, int[][] resultB, Semaphore semaphore) { - this.lineStart = lineStart; - this.colStart = colStart; - this.resultA = resultA; - this.resultB = resultB; - this.semaphore = semaphore; - } - - @Override - public void run() { - try { - semaphore.acquire(2); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - for (int i = lineStart, x = 0; i < lineStart + N / 2; i++, x++) { - for (int j = colStart, y= 0; j < colStart + N / 2; j++, y++) { - C[i][j] = resultA[x][y] + resultB[x][y]; - } - } - } - } - - static void multiplyParallel() throws InterruptedException { - ExecutorService threadPool = Executors.newWorkStealingPool(8); - - for (int i = 0; i < N; i++) { - for (int j = 0; j < N; j++) { - threadPool.submit(new MatrixMultiplyTask(i, j)); - } - } - - threadPool.shutdown(); - threadPool.awaitTermination(1, TimeUnit.MINUTES); - } - - static class MatrixMultiplyTask implements Runnable { - - private final int line; - private final int column; - public MatrixMultiplyTask(int line, int column) { - this.line = line; - this.column = column; - } - - @Override - public void run() { - C[line][column] = 0; - for (int i = 0; i < N; i++) { - C[line][column] += A[line][i] * B[i][column]; - } - } - - } - - static void multiplySerial() { - for (int i = 0; i < N; i++) { - for (int j = 0; j < N; j++) { - C[i][j] = 0; - for (int k = 0; k < N; k++) { - C[i][j] += A[i][k] * B[k][j]; - } - } - } - } - - static void initMatrixes() { - for (int i = 0; i < N; i++) { - for (int j = 0; j < N; j++) { - A[i][j] = 1; - B[i][j] = 1; - } - } - } - - static void checkResult() { - for (int i = 0; i < N; i++) { - for (int j = 0; j < N; j++) { - if (C[i][j] != N) { - System.out.println("Incorrect!"); - } - } - } - System.out.println("Correct!"); - } - - static void printMatrix(int[][] matrix) { - for (int i = 0; i < N; i++) { - for (int j = 0; j < N; j++) { - System.out.print(matrix[i][j] + " "); - } - System.out.println(""); - } - System.out.println(""); - } -} diff --git a/chapter_7/lecture_3_parallel_matrix_multiplication_naive_method/build.gradle b/chapter_7/lecture_3_parallel_matrix_multiplication_naive_method/build.gradle new file mode 100644 index 0000000..95df5f5 --- /dev/null +++ b/chapter_7/lecture_3_parallel_matrix_multiplication_naive_method/build.gradle @@ -0,0 +1,14 @@ +plugins { + id 'java' +} + +group 'org.example' +version '1.0-SNAPSHOT' + +repositories { + mavenCentral() +} + +dependencies { + testCompile group: 'junit', name: 'junit', version: '4.12' +} diff --git a/chapter_7/lecture_3_parallel_matrix_multiplication_naive_method/gradle/wrapper/gradle-wrapper.jar b/chapter_7/lecture_3_parallel_matrix_multiplication_naive_method/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..62d4c05 Binary files /dev/null and b/chapter_7/lecture_3_parallel_matrix_multiplication_naive_method/gradle/wrapper/gradle-wrapper.jar differ diff --git a/chapter_7/lecture_3_parallel_matrix_multiplication_naive_method/gradle/wrapper/gradle-wrapper.properties b/chapter_7/lecture_3_parallel_matrix_multiplication_naive_method/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..a4b4429 --- /dev/null +++ b/chapter_7/lecture_3_parallel_matrix_multiplication_naive_method/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/chapter_7/lecture_3_parallel_matrix_multiplication_naive_method/gradlew b/chapter_7/lecture_3_parallel_matrix_multiplication_naive_method/gradlew new file mode 100644 index 0000000..fbd7c51 --- /dev/null +++ b/chapter_7/lecture_3_parallel_matrix_multiplication_naive_method/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/chapter_7/lecture_3_parallel_matrix_multiplication_naive_method/gradlew.bat b/chapter_7/lecture_3_parallel_matrix_multiplication_naive_method/gradlew.bat new file mode 100644 index 0000000..5093609 --- /dev/null +++ b/chapter_7/lecture_3_parallel_matrix_multiplication_naive_method/gradlew.bat @@ -0,0 +1,104 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/chapter_7/lecture_3/settings.gradle b/chapter_7/lecture_3_parallel_matrix_multiplication_naive_method/settings.gradle similarity index 100% rename from chapter_7/lecture_3/settings.gradle rename to chapter_7/lecture_3_parallel_matrix_multiplication_naive_method/settings.gradle diff --git a/chapter_7/lecture_3_parallel_matrix_multiplication_naive_method/src/main/java/Main.java b/chapter_7/lecture_3_parallel_matrix_multiplication_naive_method/src/main/java/Main.java new file mode 100644 index 0000000..57c4389 --- /dev/null +++ b/chapter_7/lecture_3_parallel_matrix_multiplication_naive_method/src/main/java/Main.java @@ -0,0 +1,114 @@ +import java.util.Random; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; + +public class Main { + private static final int N = 2000; + + private static final int[][] A = new int[N][N]; // input array + private static final int[][] B = new int[N][N]; // input array + private static final int[][] C = new int[N][N]; // output array + + + public static void main(String[] args) throws InterruptedException { + initMatrixes(); +// printMatrix(A); +// System.out.println(""); +// printMatrix(B); + + long start = System.nanoTime(); + +// multiplySerial(); + // Serial, 2K x 2K + // Run 1 -> 68.91 seconds + // Run 2 -> 68.53 seconds + // Run 3 -> 70.86 seconds + + multiplyParallel(); + // Parallel, 2K x 2K (4 threads) + // Run 1 -> 30.00 seconds + // Run 2 -> 33.13 seconds + // Run 3 -> 36.30 seconds + + long end = System.nanoTime(); + + System.out.println("Execution time = " + (end - start)); + + checkResult(); +// printMatrix(C); + } + + static void multiplyParallel() throws InterruptedException { + ExecutorService service = Executors.newFixedThreadPool(4); + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + service.submit(new MatrixMultiplyTask(i, j)); + } + } + + service.shutdown(); + service.awaitTermination(1, TimeUnit.MINUTES); + } + + static class MatrixMultiplyTask implements Runnable { + + private final int line; + private final int col; + + public MatrixMultiplyTask(int line, int col) { + this.line = line; + this.col = col; + } + + @Override + public void run() { + C[line][col] = 0; + for (int k = 0; k < N; k++) { + C[line][col] += A[line][k] * B[k][col]; + } + } + } + + static void multiplySerial() { + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + C[i][j] = 0; + for (int k = 0; k < N; k++) { + C[i][j] += A[i][k] * B[k][j]; + } + } + } + } + + static void initMatrixes() { + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + A[i][j] = 1; + B[i][j] = 1; + } + } + } + + static void checkResult() { + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + if (C[i][j] != N) { + System.out.println("Incorrect!"); + } + } + } + System.out.println("Correct!"); + } + + static void printMatrix(int[][] matrix) { + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + System.out.print(matrix[i][j] + " "); + } + System.out.println(); + } + System.out.println(); + } +}