From 4793e2cef41be6103bc01be848f2962952ba38e1 Mon Sep 17 00:00:00 2001 From: Arefe Talebi Date: Wed, 24 Jun 2026 18:53:41 +0330 Subject: [PATCH] HW08 --- Report.md | 71 +++++++++++++++++++ src/main/java/DownloadWorker.java | 28 ++++++++ src/main/java/Main.java | 105 +++++++++++++---------------- src/main/java/ProgressMonitor.java | 4 ++ 4 files changed, 150 insertions(+), 58 deletions(-) create mode 100644 Report.md diff --git a/Report.md b/Report.md new file mode 100644 index 0000000..d2519b3 --- /dev/null +++ b/Report.md @@ -0,0 +1,71 @@ +Report + +1. start() vs run() + +What output do you get from the program? Why? + +The output is usually something like this: +Calling run() +Running in: main +Calling start() +Running in: Thread-2 + +When we call "run()" directly, no new thread is created and the code runs in the main thread. That's why "main" is printed. + +However, when we call "start()", Java creates a new thread and then executes the "run()" method inside that thread, so the thread name becomes "Thread-2". + +What's the difference between calling "start()" and "run()"? + +The "run()" method behaves like a normal method call and does not create a new thread. + +The "start()" method creates a new thread and allows concurrent execution. Internally, it automatically calls the "run()" method. + +--- + +2. Daemon Threads + +What output do you get from the program? Why? + +The output is usually: + +Main thread ends. + +Sometimes a few lines of + +Daemon thread running... + +may also appear. + +This happens because daemon threads run in the background. As soon as the main thread finishes, the JVM stops all daemon threads, even if they have not completed their work. + +What happens if you remove "thread.setDaemon(true)"? + +If we remove this line, the thread becomes a normal user thread. In this case, the JVM waits until the thread finishes all 20 iterations before terminating the program. + +What are some real-life use cases of daemon threads? + +Examples include: + +- Garbage collection +- Background logging +- Cache cleanup +- Monitoring system resources +- Periodic maintenance tasks + +--- + +3. A shorter way to create threads + +What output do you get from the program? + +Thread is running using a ...! + +What is the "() -> { ... }" syntax called? + +This syntax is called a Lambda Expression. + +How is this code different from creating a class that extends "Thread" or implements "Runnable"? + +Using lambda expressions makes the code shorter and easier to read. Instead of creating a separate class for "Runnable", we can write the thread's behavior directly where we create the thread. + +This reduces extra code and makes the program cleaner. \ No newline at end of file diff --git a/src/main/java/DownloadWorker.java b/src/main/java/DownloadWorker.java index 546de2d..6589cdd 100644 --- a/src/main/java/DownloadWorker.java +++ b/src/main/java/DownloadWorker.java @@ -22,22 +22,50 @@ public class DownloadWorker implements Runnable { @Override public void run() { // TODO: Record the chunk start time in chunkStatus. + chunkStatus.setStartTimeMs(System.currentTimeMillis()); double downloaded = 0.0; // TODO: Print a message that this chunk has started downloading. + System.out.println("Chunk #" + chunkStatus.getChunkId() + " started downloading."); while (downloaded < chunkStatus.getChunkSizeMB()) { // TODO: Generate a random sleep delay between min and max delay. + int delay = random.nextInt( + config.getMaxStepDelayMs() - config.getMinStepDelayMs() + 1) + + config.getMinStepDelayMs(); // TODO: Sleep for that delay. + try { + Thread.sleep(delay); + } catch (InterruptedException e) { + e.printStackTrace(); + } + // TODO: Generate a random download amount for this step. + double stepDownload = + config.getMinStepDownloadMB() + + (config.getMaxStepDownloadMB() - config.getMinStepDownloadMB()) * random.nextDouble(); + // TODO: Increase downloaded, but do not go beyond chunk size. + downloaded += stepDownload; + if (downloaded > chunkStatus.getChunkSizeMB()) {downloaded = chunkStatus.getChunkSizeMB(); + } + // TODO: Save the updated downloaded value into chunkStatus. + chunkStatus.setDownloadedMB(downloaded); // TODO: Optionally print step-by-step progress. + System.out.println(chunkStatus); + } // TODO: Mark the chunk as completed. + chunkStatus.setCompleted(true); + // TODO: Record the chunk end time in chunkStatus. + chunkStatus.setEndTimeMs(System.currentTimeMillis()); + // TODO: Print a message that this chunk has finished downloading. + System.out.println("Chunk #" + chunkStatus.getChunkId() + " finished downloading."); + } } diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 82bd239..de91036 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -35,8 +35,9 @@ public class Main { workerThreads.add(workerThread); // TODO: - // Students may print helpful debug information here, - // for example which chunk is assigned to which worker thread. + System.out.println( + "Chunk"+chunk.getChunkId()+ "assigned to" + workerThread.getName() + ); } // 4. Create and start monitor thread @@ -44,64 +45,52 @@ public class Main { Thread monitorThread = new Thread(monitor, "Progress-Monitor"); // TODO: - // Start the monitor thread before starting the workers - // so that progress can be displayed while downloading happens. - // - // Example idea: - // monitorThread.start(); - - // 5. Start worker threads - // TODO: - // Start each worker thread in workerThreads. - // Use a loop and call start() on each thread. - - // 6. Wait for workers to finish - // TODO: - // Wait for all worker threads to complete by calling join(). - // This should be done inside a try-catch block for InterruptedException. - // - // Hint: - // for (Thread thread : workerThreads) { - // thread.join(); - // } + monitorThread.start(); // TODO: - // After all workers finish, the monitor thread may also need to stop. - // Depending on how ProgressMonitor is implemented, students may: - // - wait for it to finish on its own, or - // - add a stopping mechanism in ProgressMonitor later. - // - // If your monitor finishes automatically, you may join it here. - - // NOTE: - // this final report may show 0 progress because no worker has actually run yet. - // Until students complete the thread start/join TODOs above, - - // 7. Print final report - System.out.println(); - System.out.println("=== Final Report ==="); - - int completedChunks = 0; - double downloadedMB = 0.0; - - for (ChunkStatus chunk : chunks) { - downloadedMB += chunk.getDownloadedMB(); - - if (chunk.isCompleted()) { - completedChunks++; + for (Thread thread : workerThreads){ + thread.start(); + } + // TODO: + try{ + for (Thread thread : workerThreads) { + thread.join(); } - - System.out.println( - "Chunk " + chunk.getChunkId() - + ": " + chunk.getDownloadedMB() - + "/" + chunk.getChunkSizeMB() - + " MB" - ); + } + catch (InterruptedException e) { + System.out.println("Main thread interrupted."); } - System.out.println(); - System.out.println("Completed chunks: " + completedChunks + "/" + chunks.size()); - System.out.println("Downloaded total: " + downloadedMB + "/" + config.getTotalSizeMB() + " MB"); - System.out.println("Simulation finished."); - } -} + // TODO: + try { + monitorThread.join(); + }catch (InterruptedException e) { + System.out.println("Monitor thread interrupted."); + } + System.out.println(); + System.out.println("=== Final Report ==="); + + int completedChunks = 0; + double downloadedMB = 0.0; + + for (ChunkStatus chunk : chunks) { + downloadedMB += chunk.getDownloadedMB(); + + if (chunk.isCompleted()) { + completedChunks++; + } + + System.out.println( + "Chunk " + chunk.getChunkId() + + ": " + chunk.getDownloadedMB() + + "/" + chunk.getChunkSizeMB() + + " MB" + ); + } + + System.out.println(); + System.out.println("Completed chunks: " + completedChunks + "/" + chunks.size()); + System.out.println("Downloaded total: " + downloadedMB + "/" + config.getTotalSizeMB() + " MB"); + System.out.println("Simulation finished."); + } + } \ No newline at end of file diff --git a/src/main/java/ProgressMonitor.java b/src/main/java/ProgressMonitor.java index 475c0e0..3f61429 100644 --- a/src/main/java/ProgressMonitor.java +++ b/src/main/java/ProgressMonitor.java @@ -57,6 +57,10 @@ public class ProgressMonitor implements Runnable { // TODO: // If all chunks are completed, print a final message and exit the loop + if (completedChunks == chunks.size()){ + System.out.println("All cchunks have been downloadeed.Monitor stopped."); + break; + } try { Thread.sleep(monitorDelayMs);