2 Commits
Author SHA1 Message Date
mahdi_Goudarzi 0429dbb844 answer theoric question 2026-06-03 18:46:12 +03:30
mahdi_Goudarzi ec73b93e38 complete code 2026-06-03 17:56:46 +03:30
9 changed files with 130 additions and 55 deletions
+1 -1
View File
@@ -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>
+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. * 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) {
+51 -11
View File
@@ -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
View File
@@ -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 ===");
+8 -11
View File
@@ -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;
} }
} }
} }
} }