From ec73b93e38241c3c5eae524363b069bbd78feb56 Mon Sep 17 00:00:00 2001 From: Mahdi Date: Wed, 3 Jun 2026 17:56:46 +0330 Subject: [PATCH 1/2] complete code --- .idea/misc.xml | 2 +- src/main/java/DownloadConfig.java | 1 + src/main/java/DownloadWorker.java | 62 ++++++++++++++++++++++++------ src/main/java/Main.java | 59 +++++++++++++--------------- src/main/java/ProgressMonitor.java | 19 ++++----- 5 files changed, 88 insertions(+), 55 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index fdc35ea..0c04b52 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -8,7 +8,7 @@ - + \ No newline at end of file diff --git a/src/main/java/DownloadConfig.java b/src/main/java/DownloadConfig.java index dc1ba3a..d95cf13 100644 --- a/src/main/java/DownloadConfig.java +++ b/src/main/java/DownloadConfig.java @@ -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) { diff --git a/src/main/java/DownloadWorker.java b/src/main/java/DownloadWorker.java index 546de2d..a1abb67 100644 --- a/src/main/java/DownloadWorker.java +++ b/src/main/java/DownloadWorker.java @@ -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); + } + + + + 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. - // TODO: Record the chunk end time in chunkStatus. - // TODO: Print a message that this chunk has finished downloading. + 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" ); + } } diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 82bd239..9094882 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -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 ==="); diff --git a/src/main/java/ProgressMonitor.java b/src/main/java/ProgressMonitor.java index 475c0e0..a220b10 100644 --- a/src/main/java/ProgressMonitor.java +++ b/src/main/java/ProgressMonitor.java @@ -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; } } + } } -- 2.54.0 From 0429dbb844d3a575b2828603e94218e035d3b62c Mon Sep 17 00:00:00 2001 From: Mahdi Date: Wed, 3 Jun 2026 18:46:12 +0330 Subject: [PATCH 2/2] answer theoric question --- Report.md | 42 ++++++++++++++++++++++++++++++++++++++++++ picture/Q1.PNG | Bin 0 -> 2936 bytes picture/Q2.PNG | Bin 0 -> 1515 bytes picture/Q3.PNG | Bin 0 -> 918 bytes 4 files changed, 42 insertions(+) create mode 100644 Report.md create mode 100644 picture/Q1.PNG create mode 100644 picture/Q2.PNG create mode 100644 picture/Q3.PNG diff --git a/Report.md b/Report.md new file mode 100644 index 0000000..21f586a --- /dev/null +++ b/Report.md @@ -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 diff --git a/picture/Q1.PNG b/picture/Q1.PNG new file mode 100644 index 0000000000000000000000000000000000000000..823145e9a1b946d6d3a51a34e579ef675a6fedb3 GIT binary patch literal 2936 zcmXw*2{aVm7ssFYDZ+#bLzF#aPqxXDJ!_IJTZj?amx#$Pj5Wq&OGd`n*GS3|KSV#3 zVTf##u`gNDjM2#SpMIVHId8f5-FMG<=e+OzoSR~8Y0SwEWd{Ionwl6~1Aqz6unmu~ zGS=i~(m6H&9koR?}2u43)D=>c5SP%BsgpzXQNNXKJ8#J<4^n2xcXA z^>h;CXS{`4^9~D3R{e_rZ8tEX9dj(Y32)_jV}x5Iw#q<JuyuM{jFLWkan{ZST6{TteazWe2SNY&ld{3b1i(9yX<8uT zi5e_MPyj+c>>=m}dG!2@!)4~qj*iOG*jjvBUyh2i^TF8t6H5?_sV`FmpR|GTIJ9s% z#s+r4e36=VFasWt{kQ4#V!AZP+u-SoxcMmGt&Qv`*FekFot-RbXUgRTsrvi2pQkj- z?@VKZskyE?Iuu7N9&g{a`RL!KhP7AS3erGV^Ce;f@^x*`*?aw>A0dA?*s#KFee!up zn+A7y@ytGl18P5R78}x_x02b6r~ZhNcfIB9=Yp8<0ibYbuZv#Q(QaE~P&x!@yBD4@ zu<`Nr_CfG8rOC~8>NsT|+jCBmgK+tB`Agd_9o4x6v!@~9FEY_BsErlW!`3sm#YyAa zRhhOV)q-H{9o< zCyQ(nov1#?)6Ph-A+I}y(}po|rN&-GZNe+mJB78u#<`#TIOnI$^|i+p&2lXw!c8)q zGW?qUet*4RxjOa((I&^NlnG{(&U0Bu1gcilf-dN$H63p2(1%4zQ37m3*7QVLU8=kz%>VJErlB!hGGgmvGxpfqKT%++_^;fZxPus>Lr!mVk zaqZcZm5Z3R&MPh>j&PMXUogmd;iD)=rS(LW5>n`W2Nqy`pZ#2;ILx`-tT#z3SgP|d zE-fLZNT%0wG6?E30aFS|j(z zv&(JrJ}h4_x){hEO>{gE0Xvlabk!Kl;8k8%`~16bt^%7XUZWU!*qRX92NnprcaL#I z^1p4xeVdtazrG$)D+Po6Bsd=b9qM7jsNe4_k&hX5a=X=UTXe`vw~WMVKggvAjG?F+HmR)PKpx% zxODpUs+o}lB#n!AeaZUwR}cV;`km6OD0W6-rbi^Cv+gQCjTGi(7&0YT~XB zFJ)qaZ{*fXxoG5TVG1h|k}$uY!_OC6BYCW{_~ZIJ74i((+^8d5x+$MxjyU#viyWza;2)7Rh>`{<9nZ&TsJ zDnpf00XH2qxvp!)8J|Dh zYyyMx$`?p#r#I%)Q`l{BY^1NL{U_n}P@pCtHS;a1UTVSL9{nSGYcWW>1{3@rY0?O2 zHRRK|_8mO#&8(|Urd(5nzG(0v`f=ldAQ6L9O-U)N;Tum#!hiGN2D!U)o}^)^`DGCu-Z+vnTFc>_^~i5+l}1=_sL8PQCY6D zwdHlc%y13|FWS^d-5XJ;*MgAzJ>XRq=|5Ng7WrC&5Oez^??}Fej zchN&9*60sT=~D$Cl!;}8Sz{FA9=HvVvqPxTkCJsN3|_+UFU?)gA*eYbD{*KRwblaLW#4cQ9cugeYsm(%00UnBt)N`PnCr{s$Y~;} z-g%3Xds9KN{wc|jzyJLcS9snct$XBwdUn#Wrg6M_fWwru7yf&C^WgxoimFlGY3F*( zbMWt}RapcaU+YiKtvL00{#4x%7Tf9rwLDwFuFG>ILlt6SRmWqIgs;*bluEew}K)G6C&mIAK!7Zz5DcjEB#PRLT$??`t#_74{z4)ogx5wz6rqTsH+O5 z3Kf<$qI~64|76)r&$VcRQeO*VlEkwuuM&UAhqVtNYez?Jne|n)W2}yfn?bZzX>viU zrJ_@9&!(BIeUEq&zKRP3EQdeH5Sy-*izXzVHE(c|M=4m;y?fDDpe(R7Y6A1WcbJbA z`ZD=1elm!yS2!k(lb(YRa{;=F3`Q?`x9|*vhF&p(t@Vg@`Vn~voIaIT1cKwL%0Bhx zKKUfvfi7NGhY){VyJ6e0L<4eZb17H8J=|!zR7W{?TifnNk!&M|+#!dU54!xhW;qtp z>$$2F{W%2Npifa*ijX~5Az)f#GImjM7~mv^O;iYl@{V3{6aDSE7@2K{S(Ao5p(M|l zzE1l(DVWvaM)znUF+lPeVxHXiLn1cjEiWp12us(?ILV8wAE6>|_UMZOz_)7340Io{ zQE(HfoCF3-{ZA*NWbDw_Tx~z{dM6`}fN{Y;SI!%~VrI0m?CGiiEb{-6p&|i*Eazl8 Zgp(hykFdTs%;-9SsiCDoy}tY3{{vI-jduV5 literal 0 HcmV?d00001 diff --git a/picture/Q2.PNG b/picture/Q2.PNG new file mode 100644 index 0000000000000000000000000000000000000000..ced060d1907f47dad01b0a3c63c446d5e9a4f071 GIT binary patch literal 1515 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1%OFJK~#8N?VRnI zs~`}CQ^2O1^kOGAVkP#mJ-H4rFyQc&#LWli$NSt>aA4qYG?CoP&(F_B+~#%r{r&Z< z^Ua)RuGiZ(uY1`#Z@23;DwA-%WeRn!*J)csY#GDH&6H>BER!!ceHX`)miStI?td=! zw1hFbPK$`YZu2y6t7}6Y52`Q6;I`M7eG}zs|A|Vz++GyhA^Re)k##t}T9%BT91DWA z6l)-fBl_R1k4)}Fntys;i&1JrElcuO>&f`Ze3!8EwQQ59Thf=W!|iK*D_rjl;FyIsgCe`zZzhz_Yl=06rCe7cV^FJR2AQcx%4h01h9~{&DdWFaQ7s z1_l7Yz`y_i7?`ISK#~hAbc9 zy*jAl4S=?v+C{SL;$qQRk#?Pe(zxyl>FOYZw%sim-po&zIuH}ezo>%`L(of@-O5A#>Eh)LAae&)b2EfRRmxv8i=O;y?N<$;v3+X-E;gP9fFm*h2`xAh9Scw{zMQ~6 z(g2h@Xk1>-Ut55ty~g}n+wU=eQu`baCIE;_ZgGUC0TO5sARlW2JJSGiqJGo>2+Fl= z5c&L5gD`Dp#wSO){fYtH(Y`)UE-!pk7>cR^(BEEEhW&1({N6p3J6z0`1=_-)osRf5 z15k4i^-KAia`_lf=R5N&wcnCoseLuJ(l;2um|!a~00RR90AOHX000aO3;=+EfdK$8 zFfafB24;8z&|b5>ntNW8z8e3!@x%H(I`+pv@*OczcxV2p^z0;jH8241UpNB@n?JsF zB4Gdk961;OVb8_;)6I5O|CDgtEf$pv@ftBNvo)2yEc~uL#P_Dd*DHpE|4$%KsehWm zNrS14Z_D^cW1Kuawp`D3d<@4snew-y8-SY-77`*ewDqap)uWuOWVIftB(% z<+bsXb3o@i^Q-nRn&W)|(6NhO%fGceoC6F1yqx1l04)Ch0tNuUz`y_i7#J7;00RR90AN^twm<$PEd61O RDK!89002ovPDHLkV1i1Xz`g(g literal 0 HcmV?d00001 diff --git a/picture/Q3.PNG b/picture/Q3.PNG new file mode 100644 index 0000000000000000000000000000000000000000..af42128e8bf34c1379cf2aa6eda9abfe00895cbe GIT binary patch literal 918 zcmeAS@N?(olHy`uVBq!ia0y~yV6*|U^Sb^uZH~Ax@7%2QbJxkA-J_G1 zxXke@^Lxf7c7_Z#4mpMek_r_J4QU=+_eA$EEIFJqt})QhqvobvzG^32Y-PVH)axI^^(1wAG>aMOmX<*TRnsHaZP_+EVM^si0z z?+$rAb-%u_qV`y9+kDe7?Ui!TSwR>!TBr^-o%+NXPrtp6{67@pb;Qda)3BpyhV@ z6{k4QZryLTVotoU&F?+3ypr9MA65j_O{)0!@t5q@&$dq8%ISMVd3N65F4FHje{0^q zTgK;l?61^c62Ef(IBWj|>ka3f1-AeEIqUg%=}UIeH=f357P0i7_?qnXDc)Z=u5RJ4 zXIJLmRF>$kdS5>m7`Q+8xvYpwKQjN7{eAl*R(b-b3x6->TUy9CeLcs$U&%M+zjS`s z{(0@T-yjki~PQ+>4j=e3RN|4wISS%EjTGQJYZy)g`Pf%7IfP&v;M4`e`u!F+;(7IV(@hJ Kb6Mw<&;$THtf;C0 literal 0 HcmV?d00001 -- 2.54.0