- Important Note
- Introduction
- Objectives 🎯
- Theoretical Questions 📝
- Practical Questions 💻
- Bonus Tasks 🌟
- Evaluation 📊
- Submission ⌛
- Additional Resources 📚
When you're opening this project on your own system, please make sure to:
-
Go to Settings/Preferences > Build, Execution, Deployment > Build Tools > Gradle.
-
Under Gradle settings, change the Gradle distribution to:
-
Use local Gradle distribution, and
-
Set the Gradle home path to your own local Gradle installation directory.
If you don’t have Gradle installed locally, you can either:
-
Install Gradle manually and configure the path, or
-
Change the setting to Use Gradle wrapper instead.
Welcome to the Sixth Advanced Programming (AP) Assignment. This project is divided into two main sections:
-
Theoretical Questions: This section is designed to deepen your understanding of advanced multithreading concepts in Java. You'll have to analyze one code block and answer questions about it.
-
Practical Questions: In this section, you'll get hands-on experience with multithreading in Java. Your code will be manually checked to ensure you've implemented the tasks using multithreading.
-
Practice more advanced concepts of multithreading and concurrency in Java.
-
Understand different approaches to synchronization and thread safety.
-
Apply concurrency techniques in practical simulations and systems.
-
Compare performance between single-threaded and multi-threaded solutions.
Note: Please answer these questions in a Markdown file (Report.md) and place it in the root directory of your fork. Include code or screenshots where you see fit.
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicDemo {
private static AtomicInteger atomicCounter = new AtomicInteger(0);
private static int normalCounter = 0;
public static void main(String[] args) throws InterruptedException {
Runnable task = () -> {
for (int i = 0; i < 1_000_000; i++) {
atomicCounter.incrementAndGet();
normalCounter++;
}
};
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Atomic Counter: " + atomicCounter);
System.out.println("Normal Counter: " + normalCounter);
}
}
Questions:
-
What output do you get from the program? Why?
-
What is the purpose of AtomicInteger in this code?
-
What thread-safety guarantees does atomicCounter.incrementAndGet() provide?
-
In which situations would using a lock be a better choice than an atomic variable?
-
Besides AtomicInteger, what other data types are available in the java.util.concurrent.atomic package?
The Monte Carlo algorithm for estimating π (pi) is a classic example of using random sampling to approximate a mathematical constant.
This project simulates random points
The simulation calculates the ratio of points that fall inside the circle to the total number of generated points.
This ratio approximates the area ratio between the circle and the square, and can be used to estimate the value of
- Area of Square:
$(2r)^2 = 4r^2$ - Area of Circle:
$\pi r^2$ - The ratio of these two:
We generate random
If the condition is satisfied, the point is considered inside the circle, and we increment the corresponding counter.
- Complete the Code: Implement the Monte Carlo simulation to estimate the value of π. The implementation should include both:
-
A single-threaded version.
-
A multi-threaded version.
- Compare the result:
- Use the benchmark results to compare the performance of the multi-threaded and single-threaded versions.
- Answer the following questions in the Report.md file
-
Was the multi-threaded implementation always faster than the single-threaded one?
-
If yes, why?
-
If not, what factors are the cause and what can you do to mitigate these issues?
-
You're building a simple multithreaded banking system that manages four bank accounts and processes transactions (deposits, withdrawals, transfers) using four input files—each handled by a separate thread.
Your task is to implement thread-safe logic for the deposit, withdraw, and transfer methods in the BankAccount class.
Note: Account setup, input parsing, and thread management are already implemented.
-
Your Task You only need to implement the following methods inside the
BankAccount
class:deposit(int amount)
withdraw(int amount)
transfer(BankAccount target, int amount)
-
Concurrency Requirements
- All methods must be thread-safe. Multiple threads may access and modify the same accounts concurrently.
- You must prevent race conditions using synchronization mechanisms such as
ReentrantLock
. - For
transfer
, you must acquire locks on both source and target accounts simultaneously. - 🔒 Note: Improper locking can lead to deadlocks. Identify the problem and prevent it from happening.
-
Note:
For the sake of simplicity in this assignment, you do not need to check whether the balance is sufficient before performing a withdrawal or a transfer. This means accounts are allowed to have negative balances, and there is no need to throw exceptions or block operations due to insufficient funds.
-
Tests are provided — run them multiple times to ensure consistent results. This helps verify that your implementation is free of race conditions and deadlocks.
-
Graphical Visualization (UI)
- Use a UI framework like JavaFX to visualize the simulation:
- Show the square and inscribed circle.
- Plot random points in real time:
- Green dots for points inside the circle.
- Red dots for points outside the circle.
- Update the estimated value of π dynamically as points are plotted.
- Plot random points in real time:
-
Benchmark
- Create a report comparing runtime vs. number of points for both single-threaded and multi-threaded runs.
- Export results as a CSV or JSON file.
- Live Charting:
- Display balance changes over time using a live chart.
Your work on this assignment will be evaluated based on:
-
Understanding of Multithreading Concepts: Your ability to accurately answer the theoretical questions, and demonstrating a deep understanding of multithreading in Java. Remember that the answers to the theoretical questions should be provided separately in a markdown file.
-
Code Quality: Your code should be well-structured, readable, and efficient. Proper use of Java conventions, including variable naming, class structure, and comments, will also be considered.
-
Don’t forget to answer the question in the Monte Carlo task within the report file.
-
Your Banking System code must pass all the provided tests.
-
Total: 100 points
- 🧠 Theoretical Questions – 20 points
- 🧮 Practical Task 1 (Monte Carlo) – 50 points
- 🏦 Practical Task 2 (Banking System) – 30 points
- 🌟 Bonus Tasks – Up to 10 extra points
- Add your mentor as a contributor to the project.
- Create a
develop
branch for implementing features. - Use Git for regular code commits.
- Push your code and the answers file to the remote repository.
- Submit a pull request to merge the
develop
branch withmain
.
The deadline for submitting your code is Wednesday, May 14 (24th of Ordibehesht)
For assistance with this assignment, you may refer to the following resources:
- Race Conditions and Critical Sections
- Java Synchronized Blocks
- Deadlock
- Deadlock Prevention
- Java ExecutorService
- Semaphore
- Java Lock
Also, you can find a wealth of knowledge from various YouTube courses. They can be a great source of learning. Alongside, joining discussions on forums and reading helpful documents can also be beneficial.