Develop #1

Open
mahdi_Goudarzi wants to merge 2 commits from develop into main
9 changed files with 130 additions and 55 deletions
+1 -1
View File
@@ -8,7 +8,7 @@
</list>
</option>
</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" />
</component>
</project>
+42
View File
@@ -0,0 +1,42 @@
# Theoretical Questions
---
## Question 1
### 1. `start()` vs `run()`
![cover](picture/Q1.PNG)
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
![cover](picture/Q2.PNG)
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
![cover](picture/Q3.PNG)
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
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 918 B

+1
View File
@@ -14,6 +14,7 @@ public class DownloadConfig {
/**
* Constructs a new DownloadConfig with specified simulation parameters.
*/
public DownloadConfig(String fileName, int totalSizeMB, int chunkCount,
int minStepDelayMs, int maxStepDelayMs,
double minStepDownloadMB, double maxStepDownloadMB) {
+51 -11
View File
@@ -21,23 +21,63 @@ public class DownloadWorker implements Runnable {
@Override
public void run() {
// TODO: Record the chunk start time in chunkStatus.
long start_time = System.currentTimeMillis();
chunkStatus.setStartTimeMs(start_time);
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()) {
// TODO: Generate a random sleep delay between min and max delay.
// TODO: Sleep for that delay.
// TODO: Generate a random download amount for this step.
// TODO: Increase downloaded, but do not go beyond chunk size.
// TODO: Save the updated downloaded value into chunkStatus.
// TODO: Optionally print step-by-step progress.
int delay = random.nextInt(config.getMaxStepDelayMs() - config.getMinStepDelayMs() + 1)
+ config.getMinStepDelayMs();
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
// TODO: Mark the chunk as completed.
// TODO: Record the chunk end time in chunkStatus.
// TODO: Print a message that this chunk has finished downloading.
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());
}
chunkStatus.setCompleted(true);
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
View File
@@ -34,50 +34,45 @@ 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 number " + chunk.getChunkId() +
"assigend to thread number "+ workerThread.getName() );
}
System.out.println("------------------------------");
System.out.println("Total Threads: " + workerThreads.size());
// 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();
// 5. Start worker threads
// TODO:
// Start each worker thread in workerThreads.
// Use a loop and call start() on each thread.
// 5. start threads
monitorThread.start();
for(Thread th:workerThreads){
th.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();
// }
for(Thread th : workerThreads){
try {
th.join();
} catch (InterruptedException e) {
System.out.println("Main thread interrupted");
}
}
// 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. Wait for monitor to finish
try {
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("=== Final Report ===");
+8 -11
View File
@@ -16,15 +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
// 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) {
@@ -44,6 +35,7 @@ public class ProgressMonitor implements Runnable {
percent = (totalDownloadedMB * 100.0) / totalSizeMB;
}
System.out.println("\u001B[34m");
System.out.printf(
"Progress for %s: %.1f/%.1f MB (%.2f%%), completed chunks: %d/%d%n",
fileName,
@@ -53,10 +45,14 @@ public class ProgressMonitor implements Runnable {
completedChunks,
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 {
Thread.sleep(monitorDelayMs);
@@ -65,5 +61,6 @@ public class ProgressMonitor implements Runnable {
return;
}
}
}
}