Compare commits
2
Commits
main
..
0429dbb844
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0429dbb844 | ||
|
|
ec73b93e38 |
Generated
+1
-1
@@ -8,7 +8,7 @@
|
|||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_25" default="true" project-jdk-name="25" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
# Theoretical Questions
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Question 1
|
||||||
|
### 1. `start()` vs `run()`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
When we use the run method, we are actually in the main thread where the run function is called and it is executed in the same main thread, meaning there is a total of 1 thread. But when we use the start method, we actually have 2 threads, where a separate thread is created and the instructions inside the run function are executed in the new thread.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
## Question 2
|
||||||
|
### 2. Daemon Threads
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
1. Since we have the Daemon state in this thread, the program terminates the daemon thread after the main thread finishes, and the desired thread cannot perform its action 20 times.
|
||||||
|
|
||||||
|
2. if we remove `thread.setDaemon(true)` this thread 20 times print "Daemon thread running..." and then program finished.
|
||||||
|
|
||||||
|
3. In real life : for example when we turn off the car . the thread that play song from radio should be killed
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
## Question 3
|
||||||
|
### 3.A shorter way to create threads
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
This syntax call `Lambda Expression`
|
||||||
|
|
||||||
|
when we use Lambda expression we will write less code, and we don't need to create a new class
|
||||||
|
but when we use Traditional model, our code is cleaner than other model, but we should write more code
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 918 B |
@@ -14,6 +14,7 @@ public class DownloadConfig {
|
|||||||
/**
|
/**
|
||||||
* Constructs a new DownloadConfig with specified simulation parameters.
|
* Constructs a new DownloadConfig with specified simulation parameters.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public DownloadConfig(String fileName, int totalSizeMB, int chunkCount,
|
public DownloadConfig(String fileName, int totalSizeMB, int chunkCount,
|
||||||
int minStepDelayMs, int maxStepDelayMs,
|
int minStepDelayMs, int maxStepDelayMs,
|
||||||
double minStepDownloadMB, double maxStepDownloadMB) {
|
double minStepDownloadMB, double maxStepDownloadMB) {
|
||||||
|
|||||||
@@ -21,23 +21,63 @@ public class DownloadWorker implements Runnable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
// TODO: Record the chunk start time in chunkStatus.
|
|
||||||
|
|
||||||
|
long start_time = System.currentTimeMillis();
|
||||||
|
chunkStatus.setStartTimeMs(start_time);
|
||||||
|
|
||||||
|
|
||||||
double downloaded = 0.0;
|
double downloaded = 0.0;
|
||||||
|
|
||||||
// TODO: Print a message that this chunk has started downloading.
|
System.out.println("The chunk number: " + chunkStatus.getChunkId() + " start" );
|
||||||
|
|
||||||
|
|
||||||
while (downloaded < chunkStatus.getChunkSizeMB()) {
|
while (downloaded < chunkStatus.getChunkSizeMB()) {
|
||||||
// TODO: Generate a random sleep delay between min and max delay.
|
|
||||||
// TODO: Sleep for that delay.
|
int delay = random.nextInt(config.getMaxStepDelayMs() - config.getMinStepDelayMs() + 1)
|
||||||
// TODO: Generate a random download amount for this step.
|
+ config.getMinStepDelayMs();
|
||||||
// TODO: Increase downloaded, but do not go beyond chunk size.
|
try {
|
||||||
// TODO: Save the updated downloaded value into chunkStatus.
|
Thread.sleep(delay);
|
||||||
// TODO: Optionally print step-by-step progress.
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
double downloadValue = (random.nextDouble()*(config.getMaxStepDownloadMB() - config.getMinStepDownloadMB()))
|
||||||
|
+ config.getMinStepDownloadMB();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(downloadValue + chunkStatus.getDownloadedMB() > chunkStatus.getChunkSizeMB()){
|
||||||
|
downloadValue = chunkStatus.getChunkSizeMB() - chunkStatus.getDownloadedMB();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
chunkStatus.setDownloadedMB(downloadValue + chunkStatus.getDownloadedMB());
|
||||||
|
downloaded = chunkStatus.getDownloadedMB();
|
||||||
|
|
||||||
|
|
||||||
|
// you can comment next line to get better output
|
||||||
|
System.out.println( "The chunk number " + chunkStatus.getChunkId()
|
||||||
|
+ "download :"+ downloadValue+"(MB)" + chunkStatus.getProgressPercentage());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Mark the chunk as completed.
|
chunkStatus.setCompleted(true);
|
||||||
// TODO: Record the chunk end time in chunkStatus.
|
|
||||||
// TODO: Print a message that this chunk has finished downloading.
|
|
||||||
|
|
||||||
|
long end_time = System.currentTimeMillis();
|
||||||
|
chunkStatus.setEndTimeMs(end_time);
|
||||||
|
|
||||||
|
|
||||||
|
System.out.println("\u001B[33m" +"The chunk number" +chunkStatus.getChunkId()
|
||||||
|
+ "Finished the download. Time:"
|
||||||
|
+( chunkStatus.getEndTimeMs() - chunkStatus.getStartTimeMs() )+ "(ms). Speed =" +
|
||||||
|
(chunkStatus.getChunkSizeMB()/( chunkStatus.getEndTimeMs() - chunkStatus.getStartTimeMs() ) *1000)
|
||||||
|
+" Mb/s"+ "\u001B[0m" );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-32
@@ -34,50 +34,45 @@ public class Main {
|
|||||||
|
|
||||||
workerThreads.add(workerThread);
|
workerThreads.add(workerThread);
|
||||||
|
|
||||||
// TODO:
|
System.out.println("Chunk number " + chunk.getChunkId() +
|
||||||
// Students may print helpful debug information here,
|
"assigend to thread number "+ workerThread.getName() );
|
||||||
// for example which chunk is assigned to which worker thread.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
System.out.println("------------------------------");
|
||||||
|
System.out.println("Total Threads: " + workerThreads.size());
|
||||||
|
|
||||||
// 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
|
|
||||||
// so that progress can be displayed while downloading happens.
|
|
||||||
//
|
|
||||||
// Example idea:
|
|
||||||
// monitorThread.start();
|
|
||||||
|
|
||||||
// 5. Start worker threads
|
// 5. start threads
|
||||||
// TODO:
|
monitorThread.start();
|
||||||
// Start each worker thread in workerThreads.
|
for(Thread th:workerThreads){
|
||||||
// Use a loop and call start() on each thread.
|
th.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 6. Wait for workers to finish
|
// 6. Wait for workers to finish
|
||||||
// TODO:
|
for(Thread th : workerThreads){
|
||||||
// Wait for all worker threads to complete by calling join().
|
try {
|
||||||
// This should be done inside a try-catch block for InterruptedException.
|
th.join();
|
||||||
//
|
} catch (InterruptedException e) {
|
||||||
// Hint:
|
System.out.println("Main thread interrupted");
|
||||||
// for (Thread thread : workerThreads) {
|
}
|
||||||
// thread.join();
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// 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:
|
// 7. Wait for monitor to finish
|
||||||
// this final report may show 0 progress because no worker has actually run yet.
|
try {
|
||||||
// Until students complete the thread start/join TODOs above,
|
monitorThread.join();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
System.out.println(" Main thread interrupted");
|
||||||
|
}
|
||||||
|
|
||||||
// 7. Print final report
|
|
||||||
|
|
||||||
|
// 8. Print final report
|
||||||
System.out.println();
|
System.out.println();
|
||||||
System.out.println("=== Final Report ===");
|
System.out.println("=== Final Report ===");
|
||||||
|
|
||||||
|
|||||||
@@ -16,15 +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.
|
|
||||||
// In each loop:
|
|
||||||
// 1. Read the downloaded size from every chunk
|
|
||||||
// 2. Add all downloaded amounts to totalDownloadedMB
|
|
||||||
// 3. Count completed chunks
|
|
||||||
// 4. Print a progress message
|
|
||||||
// 5. If completedChunks == chunks.size(), print a final monitor message and stop
|
|
||||||
// 6. Otherwise sleep for monitorDelayMs and continue
|
|
||||||
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -44,6 +35,7 @@ public class ProgressMonitor implements Runnable {
|
|||||||
percent = (totalDownloadedMB * 100.0) / totalSizeMB;
|
percent = (totalDownloadedMB * 100.0) / totalSizeMB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
System.out.println("\u001B[34m");
|
||||||
System.out.printf(
|
System.out.printf(
|
||||||
"Progress for %s: %.1f/%.1f MB (%.2f%%), completed chunks: %d/%d%n",
|
"Progress for %s: %.1f/%.1f MB (%.2f%%), completed chunks: %d/%d%n",
|
||||||
fileName,
|
fileName,
|
||||||
@@ -53,10 +45,14 @@ public class ProgressMonitor implements Runnable {
|
|||||||
completedChunks,
|
completedChunks,
|
||||||
chunks.size()
|
chunks.size()
|
||||||
);
|
);
|
||||||
|
System.out.println("\u001B[0m");
|
||||||
|
|
||||||
|
|
||||||
// TODO:
|
|
||||||
// If all chunks are completed, print a final message and exit the loop
|
if(completedChunks == chunks.size()){
|
||||||
|
System.out.println("ALL CHUNKS FINISHED");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Thread.sleep(monitorDelayMs);
|
Thread.sleep(monitorDelayMs);
|
||||||
@@ -65,5 +61,6 @@ public class ProgressMonitor implements Runnable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user