From 85955e9c61301d135f282b6eadbd95ed795607a8 Mon Sep 17 00:00:00 2001 From: Fateme Azizi Date: Sun, 7 Jun 2026 21:44:47 +0330 Subject: [PATCH 1/6] add Repoet.md --- Report.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Report.md diff --git a/Report.md b/Report.md new file mode 100644 index 0000000..e69de29 -- 2.54.0 From 7fe4d5079d6191ade3802cb6a2b4ff8c6254307b Mon Sep 17 00:00:00 2001 From: Fateme Azizi Date: Mon, 8 Jun 2026 17:03:30 +0330 Subject: [PATCH 2/6] implement Readme.md --- Report.md | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/Report.md b/Report.md index e69de29..202b545 100644 --- a/Report.md +++ b/Report.md @@ -0,0 +1,69 @@ +## Question 1: + +Output +```bash +Calling run() +Running in: main +Calling start() +Running in: Thread-2 +``` + +When we call `t1.run()`, we are just calling a method in the current thread(the main thread). +No extra thread is created. + +But if we call `t2.start()`, the code runs in a separate thread and use multithreading. + +## Question 2: + +Output: +```bash +Main thread ends. +Daemon thread running... +``` + +- The main thread finishes immediately and the other thread is stopped right after because it's a daemon thread. + + +- If we remove `thread.setDaemon(true)`, the thread won't be a daemon anymore. So when the main thread finishes, the other thread will continue and the output would be : + +```bash +Main thread ends. +Daemon thread running... +Daemon thread running... +Daemon thread running... +Daemon thread running... +Daemon thread running... +Daemon thread running... +Daemon thread running... +Daemon thread running... +Daemon thread running... +Daemon thread running... +Daemon thread running... +Daemon thread running... +Daemon thread running... +Daemon thread running... +Daemon thread running... +Daemon thread running... +Daemon thread running... +Daemon thread running... +Daemon thread running... +Daemon thread running... +``` + +- Background Tasks: Tasks that shouldn’t block the application from shutting down. + Examples: + Garbage Collection: Memory management. + Auto-save: Periodically saving temporary drafts. + Monitoring/Heartbeats: Checking system health or connection status in the background. + + +## Question 3: + +Output: +```bash +Thread is running using a ...! +``` + +- **Syntax**: This is a Lambda Expression, a shortcut in to write code blocks (functions) concisely. +- **Difference**: Your code is just a shorter version of the standard `implements Runnable` approach. +You don’t need to create a separate class anymore; you just pass the logic directly as a lambda. It’s cleaner and less boilerplate code. \ No newline at end of file -- 2.54.0 From ba67e5b73c061993bbdc32e12fa2d82e9298ca15 Mon Sep 17 00:00:00 2001 From: Fateme Azizi Date: Mon, 8 Jun 2026 17:04:13 +0330 Subject: [PATCH 3/6] implement DownloadWorker.java --- src/main/java/DownloadWorker.java | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/main/java/DownloadWorker.java b/src/main/java/DownloadWorker.java index 546de2d..83576d5 100644 --- a/src/main/java/DownloadWorker.java +++ b/src/main/java/DownloadWorker.java @@ -22,22 +22,53 @@ 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("Starting download for Chunk ID: " + chunkStatus.getChunkId()); while (downloaded < chunkStatus.getChunkSizeMB()) { + // TODO: Generate a random sleep delay between min and max delay. + long minDelay = config.getMinStepDelayMs(); + long maxDelay = config.getMaxStepDelayMs(); + long sleepTime = minDelay + (long) ((maxDelay - minDelay) * random.nextDouble()); + // TODO: Sleep for that delay. + try { + Thread.sleep(sleepTime); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + // TODO: Generate a random download amount for this step. + double minStep = config.getMinStepDownloadMB(); + double maxStep = config.getMaxStepDownloadMB(); + double downloadAmount = minStep + ((maxStep - minStep) * random.nextDouble()); + // TODO: Increase downloaded, but do not go beyond chunk size. + if(downloaded + downloadAmount >= chunkStatus.getChunkSizeMB()) + downloaded = chunkStatus.getChunkSizeMB(); + else + downloaded += downloadAmount; + // TODO: Save the updated downloaded value into chunkStatus. + chunkStatus.setDownloadedMB(downloaded); + // TODO: Optionally print step-by-step progress. + System.out.println("Chunk ID: " + chunkStatus.getChunkId() + " | downloaded: " + downloaded); } // 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 ID: " + chunkStatus.getChunkId() + " | COMPLETED!"); } } -- 2.54.0 From 2eae5431f99f8be6395e8e4e5fb9c9a3e6e46f55 Mon Sep 17 00:00:00 2001 From: Fateme Azizi Date: Mon, 8 Jun 2026 18:35:09 +0330 Subject: [PATCH 4/6] implement ProgressMonitor.java --- src/main/java/ProgressMonitor.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/ProgressMonitor.java b/src/main/java/ProgressMonitor.java index 475c0e0..0c6e4c9 100644 --- a/src/main/java/ProgressMonitor.java +++ b/src/main/java/ProgressMonitor.java @@ -16,7 +16,6 @@ public class ProgressMonitor implements Runnable { @Override public void run() { - // TODO: // Repeatedly check chunk progress until all chunks are completed. // In each loop: // 1. Read the downloaded size from every chunk @@ -45,7 +44,7 @@ public class ProgressMonitor implements Runnable { } System.out.printf( - "Progress for %s: %.1f/%.1f MB (%.2f%%), completed chunks: %d/%d%n", + "\nProgress for %s: %.1f/%.1f MB (%.2f%%), completed chunks: %d/%d%n%n", fileName, totalDownloadedMB, (double) totalSizeMB, @@ -54,9 +53,11 @@ public class ProgressMonitor implements Runnable { chunks.size() ); - - // TODO: // If all chunks are completed, print a final message and exit the loop + if(completedChunks == chunks.size()){ + System.out.println(fileName + " downloaded completely."); + break; + } try { Thread.sleep(monitorDelayMs); -- 2.54.0 From fa47ea93ae81cd06bfc72e403a5924716319697f Mon Sep 17 00:00:00 2001 From: Fateme Azizi Date: Mon, 8 Jun 2026 18:36:08 +0330 Subject: [PATCH 5/6] edit DownloadWorker.java --- src/main/java/DownloadWorker.java | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/main/java/DownloadWorker.java b/src/main/java/DownloadWorker.java index 83576d5..d3134a9 100644 --- a/src/main/java/DownloadWorker.java +++ b/src/main/java/DownloadWorker.java @@ -21,54 +21,55 @@ public class DownloadWorker implements Runnable { @Override public void run() { - // TODO: Record the chunk start time in chunkStatus. + // 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("Starting download for Chunk ID: " + chunkStatus.getChunkId()); + // Print a message that this chunk has started downloading. + System.out.println("Starting download for Chunk " + chunkStatus.getChunkId()); while (downloaded < chunkStatus.getChunkSizeMB()) { - // TODO: Generate a random sleep delay between min and max delay. + // Generate a random sleep delay between min and max delay. long minDelay = config.getMinStepDelayMs(); long maxDelay = config.getMaxStepDelayMs(); long sleepTime = minDelay + (long) ((maxDelay - minDelay) * random.nextDouble()); - // TODO: Sleep for that delay. + // Sleep for that delay. try { Thread.sleep(sleepTime); } catch (InterruptedException e) { throw new RuntimeException(e); } - // TODO: Generate a random download amount for this step. + // Generate a random download amount for this step. double minStep = config.getMinStepDownloadMB(); double maxStep = config.getMaxStepDownloadMB(); double downloadAmount = minStep + ((maxStep - minStep) * random.nextDouble()); - // TODO: Increase downloaded, but do not go beyond chunk size. + // Increase downloaded, but do not go beyond chunk size. if(downloaded + downloadAmount >= chunkStatus.getChunkSizeMB()) downloaded = chunkStatus.getChunkSizeMB(); else downloaded += downloadAmount; - // TODO: Save the updated downloaded value into chunkStatus. + // Save the updated downloaded value into chunkStatus. chunkStatus.setDownloadedMB(downloaded); - // TODO: Optionally print step-by-step progress. - System.out.println("Chunk ID: " + chunkStatus.getChunkId() + " | downloaded: " + downloaded); + // Optionally print step-by-step progress. + System.out.print("Chunk " + chunkStatus.getChunkId() + " | downloaded: "); + System.out.printf("%.2f%n", downloaded); } - // TODO: Mark the chunk as completed. + // Mark the chunk as completed. chunkStatus.setCompleted(true); - // TODO: Record the chunk end time in chunkStatus. + // 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 ID: " + chunkStatus.getChunkId() + " | COMPLETED!"); + // Print a message that this chunk has finished downloading. + System.out.println("\nChunk " + chunkStatus.getChunkId() + " | COMPLETED!\n"); } } -- 2.54.0 From ef6a05b4452ff70d83559b2bf9449ef76c08a7eb Mon Sep 17 00:00:00 2001 From: Fateme Azizi Date: Mon, 8 Jun 2026 18:36:38 +0330 Subject: [PATCH 6/6] implement Main.java --- src/main/java/Main.java | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 82bd239..3c20e1c 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -34,45 +34,51 @@ 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("Assigned Chunk " + chunk.getChunkId() + + " (" + chunk.getChunkSizeMB() + " MB) to " + workerThread.getName()); } + System.out.println(); // 4. Create and start monitor thread ProgressMonitor monitor = new ProgressMonitor(config, chunks); 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(); + monitorThread.start(); // 5. Start worker threads - // TODO: // Start each worker thread in workerThreads. // Use a loop and call start() on each thread. + for(Thread thread : workerThreads) { + thread.start(); + } // 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(); - // } - - // TODO: + // This should be done inside a try-catch block for InterruptedException + for (Thread thread : workerThreads) { + try { + thread.join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } // 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. - + try { + monitorThread.join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } // NOTE: // this final report may show 0 progress because no worker has actually run yet. // Until students complete the thread start/join TODOs above, -- 2.54.0