Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7493ce66bd | ||
|
|
57079f70f1 |
@@ -0,0 +1,46 @@
|
||||
## Answers to Theoretical Questions
|
||||
|
||||
### 1. `start()` vs `run()`
|
||||
|
||||
**Output:**
|
||||
```text
|
||||
Calling run()
|
||||
Running in: main
|
||||
Calling start()
|
||||
Running in: Thread-2
|
||||
```
|
||||
|
||||
- When calling run method, no matter what thread it is called through, the program uses the thread it is called in. So here, the run method would be runed in the main thread.
|
||||
|
||||
- On the other hand, the start method runs the run method in the thread in which it is created or overridden. In this case, it would be the second thread.
|
||||
|
||||
- Hence, the key difference between the two methods run & start is where they run the runnable method given to the thread.
|
||||
|
||||
---
|
||||
|
||||
### 2. Daemon Threads
|
||||
|
||||
**Output:**
|
||||
```text
|
||||
Main thread ends.
|
||||
Daemon thread running...
|
||||
```
|
||||
|
||||
- By turning the thread into a daemon thread, the program only runs until the last user thread finishes its task; shortly after that, the program running ends ignoring the daemon threads and their left tasks.
|
||||
|
||||
- If we remove `thread.setDaemon(true)` from the code, the thread would be considered a user thread. The program runs until the thread finishes its task. Here, it would print `Daemon thread running...` 20 times in total.
|
||||
|
||||
- Two real-life use cases of daemon threads are garbage collectors and auto-save features in editors.
|
||||
|
||||
---
|
||||
|
||||
### 3. A shorter way to create threads
|
||||
|
||||
**Output:**
|
||||
```text
|
||||
Thread is running using a ...!
|
||||
```
|
||||
|
||||
- the `() -> { ... }` syntax is called a lambda expression.
|
||||
|
||||
- By using a lambda expression, there is no need for creating a whole class to run the task. It also decreases the number of lines we need to code. So it is recommended over using another class especially if the method we want to run is not complicated.
|
||||
@@ -22,22 +22,52 @@ 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("The chunk has started downloading.");
|
||||
|
||||
while (downloaded < chunkStatus.getChunkSizeMB()) {
|
||||
// TODO: Generate a random sleep delay between min and max delay.
|
||||
int max1 = config.getMaxStepDelayMs();
|
||||
int min1 = config.getMinStepDelayMs();
|
||||
int randomDelay = random.nextInt(max1 - min1 + 1) + min1;
|
||||
|
||||
// TODO: Sleep for that delay.
|
||||
try {
|
||||
Thread.sleep(randomDelay);
|
||||
} catch (InterruptedException e) {
|
||||
//...
|
||||
}
|
||||
|
||||
// TODO: Generate a random download amount for this step.
|
||||
double max2 = config.getMaxStepDownloadMB();
|
||||
double min2 = config.getMinStepDownloadMB();
|
||||
double randomDownloadedAmount = random.nextDouble(max2 - min2 + 1) + min2;
|
||||
|
||||
// TODO: Increase downloaded, but do not go beyond chunk size.
|
||||
downloaded += randomDownloadedAmount;
|
||||
|
||||
// TODO: Save the updated downloaded value into chunkStatus.
|
||||
chunkStatus.setDownloadedMB(downloaded);
|
||||
|
||||
// TODO: Optionally print step-by-step progress.
|
||||
System.out.println(String.format("Chunk-%d: %.1f/%.1f MB",
|
||||
chunkStatus.getChunkId(),
|
||||
chunkStatus.getDownloadedMB(),
|
||||
chunkStatus.getChunkSizeMB()));
|
||||
}
|
||||
|
||||
// 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(String.format("Chunk-%d has finished downloading.", chunkStatus.getChunkId()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ public class Main {
|
||||
// TODO:
|
||||
// Students may print helpful debug information here,
|
||||
// for example which chunk is assigned to which worker thread.
|
||||
System.out.println("Chunk " + chunk.getChunkId() + " is assigned to " + workerThread.getName());
|
||||
}
|
||||
|
||||
// 4. Create and start monitor thread
|
||||
@@ -49,11 +50,15 @@ public class Main {
|
||||
//
|
||||
// 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:
|
||||
@@ -64,6 +69,13 @@ public class Main {
|
||||
// for (Thread thread : workerThreads) {
|
||||
// thread.join();
|
||||
// }
|
||||
for (Thread thread : workerThreads) {
|
||||
try {
|
||||
thread.join();
|
||||
} catch (InterruptedException e) {
|
||||
//...
|
||||
}
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// After all workers finish, the monitor thread may also need to stop.
|
||||
@@ -72,6 +84,11 @@ public class Main {
|
||||
// - add a stopping mechanism in ProgressMonitor later.
|
||||
//
|
||||
// If your monitor finishes automatically, you may join it here.
|
||||
try {
|
||||
monitorThread.join();
|
||||
} catch (InterruptedException e) {
|
||||
//...
|
||||
}
|
||||
|
||||
// NOTE:
|
||||
// this final report may show 0 progress because no worker has actually run yet.
|
||||
|
||||
@@ -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 chunks are completed.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(monitorDelayMs);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
fileName=movie.mkv
|
||||
totalSizeMB=120
|
||||
chunkCount=6
|
||||
totalSizeMB=170
|
||||
chunkCount=5
|
||||
minStepDelayMs=80
|
||||
maxStepDelayMs=200
|
||||
minStepDownloadMB=2
|
||||
|
||||
Reference in New Issue
Block a user