diff --git a/lessons/.gradle/8.13/checksums/checksums.lock b/lessons/.gradle/8.13/checksums/checksums.lock index 960c67a..30ebe77 100644 Binary files a/lessons/.gradle/8.13/checksums/checksums.lock and b/lessons/.gradle/8.13/checksums/checksums.lock differ diff --git a/lessons/.gradle/8.13/checksums/md5-checksums.bin b/lessons/.gradle/8.13/checksums/md5-checksums.bin index 0e4ba3f..0a35e9d 100644 Binary files a/lessons/.gradle/8.13/checksums/md5-checksums.bin and b/lessons/.gradle/8.13/checksums/md5-checksums.bin differ diff --git a/lessons/.gradle/8.13/checksums/sha1-checksums.bin b/lessons/.gradle/8.13/checksums/sha1-checksums.bin index b7c9f8b..9f7c612 100644 Binary files a/lessons/.gradle/8.13/checksums/sha1-checksums.bin and b/lessons/.gradle/8.13/checksums/sha1-checksums.bin differ diff --git a/lessons/.gradle/8.13/executionHistory/executionHistory.bin b/lessons/.gradle/8.13/executionHistory/executionHistory.bin index 89c5370..a890ec3 100644 Binary files a/lessons/.gradle/8.13/executionHistory/executionHistory.bin and b/lessons/.gradle/8.13/executionHistory/executionHistory.bin differ diff --git a/lessons/.gradle/8.13/executionHistory/executionHistory.lock b/lessons/.gradle/8.13/executionHistory/executionHistory.lock index 76f66aa..75aa13f 100644 Binary files a/lessons/.gradle/8.13/executionHistory/executionHistory.lock and b/lessons/.gradle/8.13/executionHistory/executionHistory.lock differ diff --git a/lessons/.gradle/8.13/fileHashes/fileHashes.bin b/lessons/.gradle/8.13/fileHashes/fileHashes.bin index 9f95a89..8ee4c8b 100644 Binary files a/lessons/.gradle/8.13/fileHashes/fileHashes.bin and b/lessons/.gradle/8.13/fileHashes/fileHashes.bin differ diff --git a/lessons/.gradle/8.13/fileHashes/fileHashes.lock b/lessons/.gradle/8.13/fileHashes/fileHashes.lock index 0ef8a01..c87c3ab 100644 Binary files a/lessons/.gradle/8.13/fileHashes/fileHashes.lock and b/lessons/.gradle/8.13/fileHashes/fileHashes.lock differ diff --git a/lessons/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/lessons/.gradle/buildOutputCleanup/buildOutputCleanup.lock index 00e9ec4..5587ac6 100644 Binary files a/lessons/.gradle/buildOutputCleanup/buildOutputCleanup.lock and b/lessons/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/lessons/.gradle/buildOutputCleanup/outputFiles.bin b/lessons/.gradle/buildOutputCleanup/outputFiles.bin index a6faea7..5ca6af5 100644 Binary files a/lessons/.gradle/buildOutputCleanup/outputFiles.bin and b/lessons/.gradle/buildOutputCleanup/outputFiles.bin differ diff --git a/lessons/.gradle/file-system.probe b/lessons/.gradle/file-system.probe index f55ab29..b4d29de 100644 Binary files a/lessons/.gradle/file-system.probe and b/lessons/.gradle/file-system.probe differ diff --git a/lessons/build.gradle b/lessons/build.gradle index 34291ce..ec6799f 100644 --- a/lessons/build.gradle +++ b/lessons/build.gradle @@ -12,6 +12,8 @@ repositories { dependencies { testImplementation platform('org.junit:junit-bom:5.10.0') testImplementation 'org.junit.jupiter:junit-jupiter' + compileOnly 'org.projectlombok:lombok:1.18.34' + annotationProcessor 'org.projectlombok:lombok:1.18.34' } test { diff --git a/lessons/src/main/java/lessons/lesson11/publisher_subscriber/App.java b/lessons/src/main/java/lessons/lesson11/publisher_subscriber/App.java new file mode 100644 index 0000000..bbbbe94 --- /dev/null +++ b/lessons/src/main/java/lessons/lesson11/publisher_subscriber/App.java @@ -0,0 +1,17 @@ +package lessons.lesson11.publisher_subscriber; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class App { + public static void main(String[] args) { + MessageQueue queue = new MessageQueue(); + + ExecutorService executor = Executors.newFixedThreadPool(2); + + executor.submit(new Publisher(queue)); + executor.submit(new Subscriber(queue)); + + executor.shutdown(); + } +} diff --git a/lessons/src/main/java/lessons/lesson11/publisher_subscriber/MessageQueue.java b/lessons/src/main/java/lessons/lesson11/publisher_subscriber/MessageQueue.java new file mode 100644 index 0000000..2409195 --- /dev/null +++ b/lessons/src/main/java/lessons/lesson11/publisher_subscriber/MessageQueue.java @@ -0,0 +1,11 @@ +package lessons.lesson11.publisher_subscriber; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +import lombok.Getter; + +@Getter +public class MessageQueue { + private final BlockingQueue queue = new LinkedBlockingQueue<>(); +} diff --git a/lessons/src/main/java/lessons/lesson11/publisher_subscriber/Publisher.java b/lessons/src/main/java/lessons/lesson11/publisher_subscriber/Publisher.java new file mode 100644 index 0000000..ce6c967 --- /dev/null +++ b/lessons/src/main/java/lessons/lesson11/publisher_subscriber/Publisher.java @@ -0,0 +1,30 @@ +package lessons.lesson11.publisher_subscriber; + +import lombok.RequiredArgsConstructor; + +import java.util.Scanner; + +@RequiredArgsConstructor +public class Publisher implements Runnable { + private final MessageQueue queue; + private volatile boolean running = true; + + @Override + public void run() { + try (Scanner scanner = new Scanner(System.in)) { + System.out.println("Words to publish ('exit' to quit):"); + while (running) { + String input = scanner.nextLine(); + if ("exit".equalsIgnoreCase(input.trim())) { + running = false; + queue.getQueue().put("exit"); + } else { + queue.getQueue().put(input); + } + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + System.out.println("Publisher interrupted."); + } + } +} diff --git a/lessons/src/main/java/lessons/lesson11/publisher_subscriber/Subscriber.java b/lessons/src/main/java/lessons/lesson11/publisher_subscriber/Subscriber.java new file mode 100644 index 0000000..db6fcc1 --- /dev/null +++ b/lessons/src/main/java/lessons/lesson11/publisher_subscriber/Subscriber.java @@ -0,0 +1,24 @@ +package lessons.lesson11.publisher_subscriber; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class Subscriber implements Runnable { + private final MessageQueue queue; + + @Override + public void run() { + try { + while (true) { + String message = queue.getQueue().take(); + if ("exit".equalsIgnoreCase(message)) { + break; + } + System.out.println("Subscriber received: " + message); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + System.out.println("Subscriber interrupted."); + } + } +} diff --git a/lessons/src/main/java/lessons/lesson11/simplethreadpool/App.java b/lessons/src/main/java/lessons/lesson11/simplethreadpool/App.java new file mode 100644 index 0000000..19e4f5b --- /dev/null +++ b/lessons/src/main/java/lessons/lesson11/simplethreadpool/App.java @@ -0,0 +1,27 @@ +package lessons.lesson11.simplethreadpool; + +public class App { + public static void main(String[] args) { + SimpleThreadPool pool = new SimpleThreadPool(10); + + for (int i = 1; i <= 10; i++) { + int taskId = i; + pool.submit(() -> { + System.out.println(Thread.currentThread().getName() + " executing task " + taskId); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }); + } + + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + + pool.shutdown(); + } +} diff --git a/lessons/src/main/java/lessons/lesson11/simplethreadpool/SimpleThreadPool.java b/lessons/src/main/java/lessons/lesson11/simplethreadpool/SimpleThreadPool.java new file mode 100644 index 0000000..6aa4449 --- /dev/null +++ b/lessons/src/main/java/lessons/lesson11/simplethreadpool/SimpleThreadPool.java @@ -0,0 +1,47 @@ +package lessons.lesson11.simplethreadpool; + +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +public class SimpleThreadPool { + + @Getter + private final BlockingQueue taskQueue; + private final List workers; + private volatile boolean isRunning = true; + + public SimpleThreadPool(int threadCount) { + this.taskQueue = new LinkedBlockingQueue<>(); + this.workers = new ArrayList<>(); + + for (int i = 0; i < threadCount; i++) { + WorkerThread worker = new WorkerThread(taskQueue); + worker.setName("Worker-" + (i + 1)); + worker.start(); + workers.add(worker); + } + + System.out.println("Thread pool initialized with " + threadCount + " threads."); + } + + public void submit(Runnable task) { + if (!isRunning) { + throw new IllegalStateException("Thread pool is shutting down."); + } + taskQueue.offer(task); + } + + public void shutdown() { + System.out.println("Shutting down thread pool..."); + isRunning = false; + + for (WorkerThread worker : workers) { + worker.stopWorker(); + } + System.out.println("Thread pool shutdown complete."); + } +} diff --git a/lessons/src/main/java/lessons/lesson11/simplethreadpool/WorkerThread.java b/lessons/src/main/java/lessons/lesson11/simplethreadpool/WorkerThread.java new file mode 100644 index 0000000..4af1033 --- /dev/null +++ b/lessons/src/main/java/lessons/lesson11/simplethreadpool/WorkerThread.java @@ -0,0 +1,29 @@ +package lessons.lesson11.simplethreadpool; + +import lombok.RequiredArgsConstructor; + +import java.util.concurrent.BlockingQueue; + +@RequiredArgsConstructor +public class WorkerThread extends Thread { + private final BlockingQueue taskQueue; + private volatile boolean running = true; + + @Override + public void run() { + while (running) { + try { + Runnable task = taskQueue.take(); + task.run(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + System.out.println(Thread.currentThread().getName() + " interrupted."); + } + } + } + + public void stopWorker() { + running = false; + this.interrupt(); + } +}