-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathExercise12.java
More file actions
143 lines (120 loc) · 6.45 KB
/
Copy pathExercise12.java
File metadata and controls
143 lines (120 loc) · 6.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package chapter12;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
/**
* ============================================================
* EXERCISE 12 — Multi-Threaded Asset & Report Downloader ⚡
* ============================================================
*
* Build a Concurrent Download & Batch Processing Engine featuring:
* 1. Thread Pool (`ExecutorService`) with configurable worker pool size.
* 2. `DownloadTask` implementing `Callable<DownloadResult>`:
* - Simulates variable latency network transfers
* - Returns downloaded byte size, duration, and status
* 3. Real-time atomic progress counters (`AtomicInteger`, `AtomicLong`).
* 4. Gathers all `Future<DownloadResult>` to print summary metrics.
* ============================================================
*/
class DownloadResult {
private String filename;
private long bytesDownloaded;
private long durationMs;
private boolean success;
public DownloadResult(String filename, long bytesDownloaded, long durationMs, boolean success) {
this.filename = filename;
this.bytesDownloaded = bytesDownloaded;
this.durationMs = durationMs;
this.success = success;
}
public String getFilename() { return filename; }
public long getBytesDownloaded() { return bytesDownloaded; }
public long getDurationMs() { return durationMs; }
public boolean isSuccess() { return success; }
@Override
public String toString() {
return String.format(" [%s] %-25s | %,8d KB | %4d ms | %s",
success ? "✓" : "❌", filename, bytesDownloaded / 1024, durationMs, success ? "DONE" : "FAILED");
}
}
class DownloadWorker implements Callable<DownloadResult> {
private String filename;
private long expectedSizeBytes;
private static final AtomicInteger activeThreads = new AtomicInteger(0);
public DownloadWorker(String filename, long expectedSizeBytes) {
this.filename = filename;
this.expectedSizeBytes = expectedSizeBytes;
}
@Override
public DownloadResult call() {
int currentActive = activeThreads.incrementAndGet();
long startTime = System.currentTimeMillis();
try {
// Simulate variable network speed (100ms - 400ms)
long simulatedDelay = (long) (100 + (Math.random() * 300));
Thread.sleep(simulatedDelay);
long elapsed = System.currentTimeMillis() - startTime;
return new DownloadResult(filename, expectedSizeBytes, elapsed, true);
} catch (InterruptedException e) {
return new DownloadResult(filename, 0, System.currentTimeMillis() - startTime, false);
} finally {
activeThreads.decrementAndGet();
}
}
}
public class Exercise12 {
public static void main(String[] args) {
System.out.println("╔══════════════════════════════════════════════════╗");
System.out.println("║ ⚡ MULTI-THREADED ASSET DOWNLOADER ║");
System.out.println("╚══════════════════════════════════════════════════╝");
int workerPoolSize = 4;
ExecutorService pool = Executors.newFixedThreadPool(workerPoolSize);
List<DownloadWorker> tasks = List.of(
new DownloadWorker("jdk-21-windows-x64.msi", 185_000_000L),
new DownloadWorker("springboot-framework.zip", 42_500_000L),
new DownloadWorker("database_backup_2026.sql", 650_000_000L),
new DownloadWorker("ml_dataset_weights.bin", 320_000_000L),
new DownloadWorker("ui_assets_bundle.tar.gz", 18_200_000L),
new DownloadWorker("video_tutorial_1080p.mp4", 450_000_000L),
new DownloadWorker("microservices_docs.pdf", 5_800_000L),
new DownloadWorker("security_certificates.pem", 120_000L)
);
System.out.printf("Dispatching %,d download tasks across %d worker threads in pool...%n%n",
tasks.size(), workerPoolSize);
long overallStart = System.currentTimeMillis();
try {
// Submit all tasks concurrently
List<Future<DownloadResult>> futures = pool.invokeAll(tasks);
System.out.println("--- DOWNLOAD COMPLETION LOGS ---");
long totalBytesDownloaded = 0;
int successfulDownloads = 0;
for (Future<DownloadResult> f : futures) {
DownloadResult result = f.get(); // Await each result
System.out.println(result);
if (result.isSuccess()) {
totalBytesDownloaded += result.getBytesDownloaded();
successfulDownloads++;
}
}
long totalTimeMs = System.currentTimeMillis() - overallStart;
System.out.println("\n╔══════════════════════════════════════════════════╗");
System.out.println("║ 📊 DOWNLOAD SESSION REPORT ║");
System.out.println("╠══════════════════════════════════════════════════╣");
System.out.printf("║ Files Transferred : %d / %-24d ║%n", successfulDownloads, tasks.size());
System.out.printf("║ Total Data Downloaded: %,.2f MB%-23s ║%n", (totalBytesDownloaded / (1024.0 * 1024.0)), "");
System.out.printf("║ Total Wall-Clock Time: %d ms%-28s ║%n", totalTimeMs, "");
System.out.printf("║ Throughput Efficiency: %,.2f MB/sec%-19s ║%n",
(totalBytesDownloaded / (1024.0 * 1024.0)) / (totalTimeMs / 1000.0), "");
System.out.println("╚══════════════════════════════════════════════════╝");
} catch (Exception e) {
System.out.println("❌ Manager Failure: " + e.getMessage());
} finally {
pool.shutdown();
}
}
}