6 Commits
Author SHA1 Message Date
Fateme_Azizi ef6a05b445 implement Main.java 2026-06-08 18:36:38 +03:30
Fateme_Azizi fa47ea93ae edit DownloadWorker.java 2026-06-08 18:36:08 +03:30
Fateme_Azizi 2eae5431f9 implement ProgressMonitor.java 2026-06-08 18:35:09 +03:30
Fateme_Azizi ba67e5b73c implement DownloadWorker.java 2026-06-08 17:04:13 +03:30
Fateme_Azizi 7fe4d5079d implement Readme.md 2026-06-08 17:03:30 +03:30
Fateme_Azizi 85955e9c61 add Repoet.md 2026-06-07 21:44:47 +03:30
4 changed files with 137 additions and 29 deletions
+69
View File
@@ -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 shouldnt 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 dont need to create a separate class anymore; you just pass the logic directly as a lambda. Its cleaner and less boilerplate code.
+43 -11
View File
@@ -21,23 +21,55 @@ public class DownloadWorker implements Runnable {
@Override @Override
public void run() { 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; double downloaded = 0.0;
// TODO: Print a message that this chunk has started downloading. // Print a message that this chunk has started downloading.
System.out.println("Starting download for Chunk " + chunkStatus.getChunkId());
while (downloaded < chunkStatus.getChunkSizeMB()) { while (downloaded < chunkStatus.getChunkSizeMB()) {
// TODO: Generate a random sleep delay between min and max delay.
// TODO: Sleep for that delay. // Generate a random sleep delay between min and max delay.
// TODO: Generate a random download amount for this step. long minDelay = config.getMinStepDelayMs();
// TODO: Increase downloaded, but do not go beyond chunk size. long maxDelay = config.getMaxStepDelayMs();
// TODO: Save the updated downloaded value into chunkStatus. long sleepTime = minDelay + (long) ((maxDelay - minDelay) * random.nextDouble());
// TODO: Optionally print step-by-step progress.
// Sleep for that delay.
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
// Generate a random download amount for this step.
double minStep = config.getMinStepDownloadMB();
double maxStep = config.getMaxStepDownloadMB();
double downloadAmount = minStep + ((maxStep - minStep) * random.nextDouble());
// Increase downloaded, but do not go beyond chunk size.
if(downloaded + downloadAmount >= chunkStatus.getChunkSizeMB())
downloaded = chunkStatus.getChunkSizeMB();
else
downloaded += downloadAmount;
// Save the updated downloaded value into chunkStatus.
chunkStatus.setDownloadedMB(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.
// TODO: Record the chunk end time in chunkStatus. chunkStatus.setCompleted(true);
// TODO: Print a message that this chunk has finished downloading.
// Record the chunk end time in chunkStatus.
chunkStatus.setEndTimeMs(System.currentTimeMillis());
// Print a message that this chunk has finished downloading.
System.out.println("\nChunk " + chunkStatus.getChunkId() + " | COMPLETED!\n");
} }
} }
+20 -14
View File
@@ -34,45 +34,51 @@ public class Main {
workerThreads.add(workerThread); workerThreads.add(workerThread);
// TODO:
// Students may print helpful debug information here, // Students may print helpful debug information here,
// for example which chunk is assigned to which worker thread. // 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 // 4. Create and start monitor thread
ProgressMonitor monitor = new ProgressMonitor(config, chunks); ProgressMonitor monitor = new ProgressMonitor(config, chunks);
Thread monitorThread = new Thread(monitor, "Progress-Monitor"); Thread monitorThread = new Thread(monitor, "Progress-Monitor");
// TODO:
// Start the monitor thread before starting the workers // Start the monitor thread before starting the workers
// so that progress can be displayed while downloading happens. // so that progress can be displayed while downloading happens.
// //
// Example idea: // Example idea:
// monitorThread.start(); monitorThread.start();
// 5. Start worker threads // 5. Start worker threads
// TODO:
// Start each worker thread in workerThreads. // Start each worker thread in workerThreads.
// Use a loop and call start() on each thread. // Use a loop and call start() on each thread.
for(Thread thread : workerThreads) {
thread.start();
}
// 6. Wait for workers to finish // 6. Wait for workers to finish
// TODO:
// Wait for all worker threads to complete by calling join(). // Wait for all worker threads to complete by calling join().
// This should be done inside a try-catch block for InterruptedException. // This should be done inside a try-catch block for InterruptedException
// for (Thread thread : workerThreads) {
// Hint: try {
// for (Thread thread : workerThreads) { thread.join();
// thread.join(); } catch (InterruptedException e) {
// } throw new RuntimeException(e);
}
// TODO: }
// After all workers finish, the monitor thread may also need to stop. // After all workers finish, the monitor thread may also need to stop.
// Depending on how ProgressMonitor is implemented, students may: // Depending on how ProgressMonitor is implemented, students may:
// - wait for it to finish on its own, or // - wait for it to finish on its own, or
// - add a stopping mechanism in ProgressMonitor later. // - add a stopping mechanism in ProgressMonitor later.
// //
// If your monitor finishes automatically, you may join it here. // If your monitor finishes automatically, you may join it here.
try {
monitorThread.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
// NOTE: // NOTE:
// this final report may show 0 progress because no worker has actually run yet. // this final report may show 0 progress because no worker has actually run yet.
// Until students complete the thread start/join TODOs above, // Until students complete the thread start/join TODOs above,
+5 -4
View File
@@ -16,7 +16,6 @@ public class ProgressMonitor implements Runnable {
@Override @Override
public void run() { public void run() {
// TODO:
// Repeatedly check chunk progress until all chunks are completed. // Repeatedly check chunk progress until all chunks are completed.
// In each loop: // In each loop:
// 1. Read the downloaded size from every chunk // 1. Read the downloaded size from every chunk
@@ -45,7 +44,7 @@ public class ProgressMonitor implements Runnable {
} }
System.out.printf( 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, fileName,
totalDownloadedMB, totalDownloadedMB,
(double) totalSizeMB, (double) totalSizeMB,
@@ -54,9 +53,11 @@ public class ProgressMonitor implements Runnable {
chunks.size() chunks.size()
); );
// TODO:
// If all chunks are completed, print a final message and exit the loop // 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 { try {
Thread.sleep(monitorDelayMs); Thread.sleep(monitorDelayMs);