A concurrent Java application that reads multiple CSV sales files in parallel with a thread pool, merges the results, and produces an aggregated sales report on the console and in report.txt.
- Parallel processing: each CSV file is parsed on its own worker thread using a fixed-size
ExecutorService - Builder-based configuration: thread count, input folder, output file, header handling, and delimiter
- Aggregated analytics: total revenue, total quantity, averages, top-selling product, and top revenue category
- Category breakdowns: revenue and units sold per category
- Fault tolerance: malformed rows are logged and skipped without stopping the run
- Auto-discovery: every
.csvfile indata/is processed automatically
┌──────────────────────────┐
│ ProcessorConfig.Builder │
└────────────┬─────────────┘
▼
data/*.csv ──▶ ExecutorService (fixed thread pool)
├── CsvFileProcessor ──▶ Future<List<SalesRecord>>
├── CsvFileProcessor ──▶ Future<List<SalesRecord>>
└── CsvFileProcessor ──▶ Future<List<SalesRecord>>
│
▼
ReportAggregator ──▶ console + report.txt
- Build an immutable
ProcessorConfigwith the Builder pattern. - Find every
.csvfile in the input folder. - Submit one
CsvFileProcessor(aCallable) per file to the thread pool. - Collect each file's records through its
Future. - Shut down the pool cleanly.
- Aggregate the records and write the report.
MultiThreadedFileProcessor/
├── src/
│ ├── Main.java # Entry point and orchestration
│ ├── config/ProcessorConfig.java # Immutable config + Builder
│ ├── model/SalesRecord.java # One CSV row
│ ├── processor/CsvFileProcessor.java # Callable that parses one file
│ └── report/ReportAggregator.java # Aggregation and report output
├── data/
│ ├── sales_january.csv
│ ├── sales_february.csv
│ └── sales_march.csv
├── report.txt # Sample generated report
├── run.sh # Build & run (macOS / Linux)
└── run.bat # Build & run (Windows)
Requirements: JDK 11 or later (java -version to check)
cd "Module - 2/MultiThreadedFileProcessor"
./run.sh # macOS / Linux
run.bat # Windows (or double-click it)Run these from the project root so the data/ folder is found.
javac -d out src/Main.java src/model/SalesRecord.java src/config/ProcessorConfig.java \
src/processor/CsvFileProcessor.java src/report/ReportAggregator.java
java -cp out MainOn Windows, use \ instead of / in the paths.
[Thread: pool-1-thread-1] Processing: data/sales_february.csv
[Thread: pool-1-thread-2] Processing: data/sales_january.csv
[Thread: pool-1-thread-3] Processing: data/sales_march.csv
...
=======================================================
SALES AGGREGATED REPORT
=======================================================
Total Records Processed : 25
Total Quantity Sold : 915 units
Total Revenue : $57,650.85
Average Revenue/Record : $2,306.03
Top-Selling Product : Socks
Top Revenue Category : Electronics
The full report, including per-category breakdowns, is saved to report.txt.
Each CSV file must have a header row followed by data rows:
product,category,quantity,price
Laptop,Electronics,5,999.99
T-Shirt,Clothing,20,19.99Drop additional .csv files into data/ and they'll be picked up on the next run.
| Problem | Fix |
|---|---|
java / javac not found |
Install a JDK (not just a JRE) and make sure it's on your PATH |
No CSV files found |
Run from the project root; confirm data/ contains .csv files |
permission denied: ./run.sh |
Run chmod +x run.sh once |
| Window closes instantly (Windows) | Run run.bat from Command Prompt instead of double-clicking |
ExecutorService,Callable, andFuturefor concurrent tasks- Builder pattern for immutable configuration objects
- Stream API and
Map.mergefor aggregation try-with-resourcesfor buffered file reading and writing- Packaged source layout (
config,model,processor,report)