使用Java的银行交易系统
为了理解,必须对Java OOP、 Java多线程和Java中断异常有很强的掌握。如果没有通过它们作为标题本身就是多线程的纯粹实现。
方法:
- 菜鸟方法
- 多线程方法
- 多线程方法中的同步调用
为了理解,让我们考虑一个例子来实现这个方法。
插图:
我们将讨论使用Java的银行交易系统的体系结构。在这篇社论中,我会牵着你的手,带你走完整个交易流程,让你轻松看懂,甚至给你的朋友解释。为简单起见,我们考虑了一个有 5 个所有者(Arnab、Monodwip、Mukta、Rinkel 和 Shubham)的联合银行账户,初始余额为一百美元(100 美元)。账户交易情况如下:
Name | Balance($) | Withdrawal($) | Deposit($) | Comment | Final Balance($) |
---|---|---|---|---|---|
Arnab | 100 | 20 | Arnab has withdrawn 20 Balance after withdrawal: 80 | 80 | |
Monodwip | 80 | 40 | Monodwip withdrawn 40 Balance after withdrawal: 40 | 40 | |
Mukta | 40 | 35 | Mukta deposited 35 Balance after deposit: 75 | 75 | |
Rinkel | 75 | 80 | Rinkel you can not withdraw 80 your balance is: 75 | 75 | |
Shubham | 75 | 40 | Shubham withdrawn 40 Balance after withdrawal: 35 | 35 |
方法一:菜鸟方法
我们在“Bank”类中声明了“withdraw”和“deposit”方法,并通过创建Bank类的对象“obj”从驱动程序类“GFG”访问它们。
例子
Java
// Java Program to Illlustarte Rookie Approach
// In Banking transaction system
// Class 1
// Bank class
// Defining the banking transaction
class Bank {
// Initial balance $100
int total = 100;
// Money withdrawal method. Withdraw only if
// total money greater than or equal to the money
// requested for withdrawal
// Method
// To withdraw money
void withdrawn(String name, int withdrawal)
{
if (total >= withdrawal) {
System.out.println(name + " withdrawn "
+ withdrawal);
total = total - withdrawal;
System.out.println("Balance after withdrawal: "
+ total);
// Making the thread sleep for 1 second after
// each withdrawal
// Try block to check for exceptions
try {
// Making thread t osleep for 1 second
Thread.sleep(1000);
}
// Catch block to handle the exceptions
catch (InterruptedException e) {
// Display the exception along with line
// number
// using printStacktrace() method
e.printStackTrace();
}
}
// If the money requested for withdrawal is greater
// than the balance then deny transaction*/
else {
// Print statements
System.out.println(name
+ " you can not withdraw "
+ withdrawal);
System.out.println("your balance is: " + total);
// Making the thread sleep for 1 second after
// each transaction failure
// Try block to check for exceptions
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// Method - to deposit money
// Accept money whenever deposited
void deposit(String name, int deposit)
{
System.out.println(name + " deposited " + deposit);
total = total + deposit;
System.out.println("Balance after deposit: "
+ total);
// Making the thread sleep for 1 second after
// each deposit
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// Class 2
// main class
class GFG {
// Main driver method
public static void main(String[] args)
{
// Declaring an object of Bank class and calling the
// withdarwn and deposit methods with suitable
// parameters
// Creating object of class 1 inside main()
Bank obj = new Bank();
// Custom input - Transactions
obj.withdrawn("Arnab", 20);
obj.withdrawn("Monodwip", 40);
obj.deposit("Mukta", 35);
obj.withdrawn("Rinkel", 80);
obj.withdrawn("Shubham", 40);
}
}
Java
// Java Program to Illlustarte Multithreading Approach
// In Banking transaction system
// Class 1
// Helper class
class Bank {
// Initial custom balance
int total = 100;
// Money withdrawal method. Withdraw only if total money
// greater than or equal to the money requested for
// withdrawal
void withdrawn(String name, int withdrawal)
{
if (total >= withdrawal) {
System.out.println(name + " withdrawn "
+ withdrawal);
total = total - withdrawal;
System.out.println(total);
// Making the thread sleep for 1 second after
// each withdrawal
// Try block to check for exceptions
try {
// Making thread to sleep for 1 second
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
// Else if the money requested for withdrawal is
// greater than the balance then deny transaction
else {
System.out.println(name
+ " you can not withdraw "
+ withdrawal);
System.out.println("your balance is: " + total);
// Making the thread sleep for 1 second after
// each transaction failure
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// Method - To deposit money
// Accepting money whenever deposited
void deposit(String name, int deposit)
{
System.out.println(name + " deposited " + deposit);
total = total + deposit;
System.out.println("Balance after deposit: "
+ total);
// Making the thread sleep for 1 second after
// each deposit
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// Method - Withdraw method
// Called from ThreadWithdrawal class
// using the object of Bank class passed
// from the main() method
class ThreadWithdrawal extends Thread {
Bank object;
String name;
int dollar;
// Constructor of this method
ThreadWithdrawal(Bank ob, String name, int money)
{
this.object = ob;
this.name = name;
this.dollar = money;
}
// run() method for thread
public void run() { object.withdrawn(name, dollar); }
}
// Deposit method is called from ThreadDeposit class
// using the object of Bank class passed
// from the main method
class ThreadDeposit extends Thread {
Bank object;
String name;
int dollar;
ThreadDeposit(Bank ob, String name, int money)
{
// This keyword refers t ocurrent instance itself
this.object = ob;
this.name = name;
this.dollar = money;
}
public void run() { object.deposit(name, dollar); }
}
// Class 2
// Main class
class GFG {
// Main driver method
public static void main(String[] args)
{
// Declaring an object of Bank class and passing the
// object along with other parameters to the
// ThreadWithdrawal and ThreadDeposit class. This
// will be required to call withdrawn and deposit
// methods from those class
// Creating an object of class1
Bank obj = new Bank();
ThreadWithdrawal t1
= new ThreadWithdrawal(obj, "Arnab", 20);
ThreadWithdrawal t2
= new ThreadWithdrawal(obj, "Monodwip", 40);
ThreadDeposit t3
= new ThreadDeposit(obj, "Mukta", 35);
ThreadWithdrawal t4
= new ThreadWithdrawal(obj, "Rinkel", 80);
ThreadWithdrawal t5
= new ThreadWithdrawal(obj, "Shubham", 40);
// When a program calls the start() method, a new
// thread is created and then the run() method is
// executed.
// Starting threads created above
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
Java
// Java Program to Illlustarte Multithreading Approach
// With Synchronization In Banking transaction system
// Class 1
// Helper class
class Bank {
// Initial balance $100
static int total = 100;
// Money withdrawal method. Withdraw only if total money
// greater than or equal to the money requested for
// withdrawal
static synchronized void withdrawn(String name,
int withdrawal)
{
if (total >= withdrawal) {
System.out.println(name + " withdrawn "
+ withdrawal);
total = total - withdrawal;
System.out.println("Balance after withdrawal: "
+ total);
/* Making the thread sleep for 1 second after
each withdrawal.*/
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
// If the money requested for withdrawal is greater
// than the balance then deny transaction
else {
System.out.println(name
+ " you can not withdraw "
+ withdrawal);
System.out.println("your balance is: " + total);
// Making the thread sleep for 1 second after
// each transaction failure
// Try block to check for exceptions
try {
// Making thread to sleep for 1 second
Thread.sleep(1000);
}
// Catch bloc kto handle exceptions
catch (InterruptedException e) {
// Displa ythe line number where exception
// occured
// Usign printStackTrace() method
e.printStackTrace();
}
}
}
// Method - Deposit method
// Accepting money whenever deposited
static synchronized void deposit(String name,
int deposit)
{
System.out.println(name + " deposited " + deposit);
total = total + deposit;
System.out.println("Balance after deposit: "
+ total);
// Making the thread sleep for 1 second
// after each deposit
// Try block to check for exceptions
try {
// Making thread to sleep for 1 second
Thread.sleep(1000);
}
// Catch block to handle InterruptedException
// exception
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// Method - Withdraw
// It is called from ThreadWithdrawal class using
// the object of Bank class passed from the main method
class ThreadWithdrawal extends Thread {
// Attributes of thid class
Bank object;
String name;
int dollar;
// Constructor of this class
ThreadWithdrawal(Bank ob, String name, int money)
{
// This keyword refers to parent class
this.object = ob;
this.name = name;
this.dollar = money;
}
// run() method for the thread
public void run() { object.withdrawn(name, dollar); }
}
// Deposit method is called from ThreadDeposit class using
// the object of Bank class passed from the main method*/
// Class 2
// Helper classs extending Thread class
class ThreadDeposit extends Thread {
Bank object;
String name;
int dollar;
ThreadDeposit(Bank ob, String name, int money)
{
this.object = ob;
this.name = name;
this.dollar = money;
}
public void run() { object.deposit(name, dollar); }
}
// Class 3
// Main class
class GFG {
// Main driver method
public static void main(String[] args)
{
// Declaring an object of Bank class and passing the
// object along with other parameters to the
// ThreadWithdrawal and ThreadDeposit class. This
// will be required to call withdrawn and deposit
// methods from those class
// Creating object of above class inside main()
Bank obj = new Bank();
// Creating threads
ThreadWithdrawal t1
= new ThreadWithdrawal(obj, "Arnab", 20);
ThreadWithdrawal t2
= new ThreadWithdrawal(obj, "Monodwip", 40);
ThreadDeposit t3
= new ThreadDeposit(obj, "Mukta", 35);
ThreadWithdrawal t4
= new ThreadWithdrawal(obj, "Rinkel", 80);
ThreadWithdrawal t5
= new ThreadWithdrawal(obj, "Shubham", 40);
// When a program calls the start() method, a new
// thread is created and then the run() method is
// executed
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
输出:
C:\Users\USER\Desktop\LearnCoding\MultiThreading>javac GFG.java
C:\Users\USER\Desktop\LearnCoding\MultiThreading>java GFG
Arnab withdrawn 20
Balance after withdrawal: 80
//After 1 Second
Monodwip withdrawn 40
Balance after withdrawal: 40
//After 1 Second
Mukta deposited 35
Balance after deposit: 75
//After 1 Second
Rinkel you can not withdraw 80
your balance is: 75
//After 1 Second
Shubham withdrawn 40
Balance after withdrawal: 35
Rookie 方法的缺点:
不能有两个人同时进行交易,需要等待前者完成交易。如果人数很多,那么我们需要等待,直到轮到我们。为了演示这个问题,我们在下面提供的视频中让线程在每个事务期间休眠 3 秒。在现实生活中,这种方法需要很长时间才能在实际交易项目中实现。
方法 2:多线程方法
多线程如何提供帮助?
多线程允许不同的线程同时工作,而无需相互依赖。如此大的一组线程可以同时执行一个操作。
例子
Java
// Java Program to Illlustarte Multithreading Approach
// In Banking transaction system
// Class 1
// Helper class
class Bank {
// Initial custom balance
int total = 100;
// Money withdrawal method. Withdraw only if total money
// greater than or equal to the money requested for
// withdrawal
void withdrawn(String name, int withdrawal)
{
if (total >= withdrawal) {
System.out.println(name + " withdrawn "
+ withdrawal);
total = total - withdrawal;
System.out.println(total);
// Making the thread sleep for 1 second after
// each withdrawal
// Try block to check for exceptions
try {
// Making thread to sleep for 1 second
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
// Else if the money requested for withdrawal is
// greater than the balance then deny transaction
else {
System.out.println(name
+ " you can not withdraw "
+ withdrawal);
System.out.println("your balance is: " + total);
// Making the thread sleep for 1 second after
// each transaction failure
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// Method - To deposit money
// Accepting money whenever deposited
void deposit(String name, int deposit)
{
System.out.println(name + " deposited " + deposit);
total = total + deposit;
System.out.println("Balance after deposit: "
+ total);
// Making the thread sleep for 1 second after
// each deposit
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// Method - Withdraw method
// Called from ThreadWithdrawal class
// using the object of Bank class passed
// from the main() method
class ThreadWithdrawal extends Thread {
Bank object;
String name;
int dollar;
// Constructor of this method
ThreadWithdrawal(Bank ob, String name, int money)
{
this.object = ob;
this.name = name;
this.dollar = money;
}
// run() method for thread
public void run() { object.withdrawn(name, dollar); }
}
// Deposit method is called from ThreadDeposit class
// using the object of Bank class passed
// from the main method
class ThreadDeposit extends Thread {
Bank object;
String name;
int dollar;
ThreadDeposit(Bank ob, String name, int money)
{
// This keyword refers t ocurrent instance itself
this.object = ob;
this.name = name;
this.dollar = money;
}
public void run() { object.deposit(name, dollar); }
}
// Class 2
// Main class
class GFG {
// Main driver method
public static void main(String[] args)
{
// Declaring an object of Bank class and passing the
// object along with other parameters to the
// ThreadWithdrawal and ThreadDeposit class. This
// will be required to call withdrawn and deposit
// methods from those class
// Creating an object of class1
Bank obj = new Bank();
ThreadWithdrawal t1
= new ThreadWithdrawal(obj, "Arnab", 20);
ThreadWithdrawal t2
= new ThreadWithdrawal(obj, "Monodwip", 40);
ThreadDeposit t3
= new ThreadDeposit(obj, "Mukta", 35);
ThreadWithdrawal t4
= new ThreadWithdrawal(obj, "Rinkel", 80);
ThreadWithdrawal t5
= new ThreadWithdrawal(obj, "Shubham", 40);
// When a program calls the start() method, a new
// thread is created and then the run() method is
// executed.
// Starting threads created above
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
输出:
现在多线程方法存在某些问题,如下所列:
当多个线程尝试同时执行特定操作时,可能会出现错误输出,这是因为所有线程一次都在更新相同的资源。在上面的输出中,由于同样的原因,我们得到了负数的平衡。
如何处理多人同时尝试访问同一个操作的情况?
如果多个线程一次访问单个资源,则存在错误输出的可能性。这种不受欢迎的现象被定义为数据竞赛。
假设我们的联名银行账户中有 100 美元。为了欺骗银行家,我们俩可以同时要求 100 美元。系统将创建一个对象,分配 2 个线程并将它们传递给提款方法。在这个过程结束时,我们俩都会有 100 美元!
为了解决这个问题,工程师提出了同步概念。
方法 3:将同步与多线程结合
同步为对象提供了一个锁定并声明了一个敏感区域(取款和存款方法)。一个对象可以有多个线程,但敏感区域一次只能被 1 个线程访问。线程调度器选择线程的执行顺序。由于它是一个随机过程,因此每种解释的输出都不同。
为什么要使用静态同步?
假设我们有 5 个线程类,每个类有 1 个对象。每个对象都有多个线程。现在敏感区域将一次被 5 个线程访问!为了解决这个问题,工程师提出了静态同步的想法。我们为班级提供了一个锁。该类将一次选择 1 个对象。物体将依次选择 1 个线程并通过敏感区域。
同步多线程执行是否比没有多线程的正常执行慢?
否。一项任务花费在等待另一项任务上的时间被视为开销。在同步多线程中,这个开销时间可用于做其他生产性工作,直到等待线程从线程调度程序获得密钥以进入同步区域。因此,在同步多线程执行的情况下,开销将是最小的,因此我们可以预期它会更快。
例子
Java
// Java Program to Illlustarte Multithreading Approach
// With Synchronization In Banking transaction system
// Class 1
// Helper class
class Bank {
// Initial balance $100
static int total = 100;
// Money withdrawal method. Withdraw only if total money
// greater than or equal to the money requested for
// withdrawal
static synchronized void withdrawn(String name,
int withdrawal)
{
if (total >= withdrawal) {
System.out.println(name + " withdrawn "
+ withdrawal);
total = total - withdrawal;
System.out.println("Balance after withdrawal: "
+ total);
/* Making the thread sleep for 1 second after
each withdrawal.*/
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
// If the money requested for withdrawal is greater
// than the balance then deny transaction
else {
System.out.println(name
+ " you can not withdraw "
+ withdrawal);
System.out.println("your balance is: " + total);
// Making the thread sleep for 1 second after
// each transaction failure
// Try block to check for exceptions
try {
// Making thread to sleep for 1 second
Thread.sleep(1000);
}
// Catch bloc kto handle exceptions
catch (InterruptedException e) {
// Displa ythe line number where exception
// occured
// Usign printStackTrace() method
e.printStackTrace();
}
}
}
// Method - Deposit method
// Accepting money whenever deposited
static synchronized void deposit(String name,
int deposit)
{
System.out.println(name + " deposited " + deposit);
total = total + deposit;
System.out.println("Balance after deposit: "
+ total);
// Making the thread sleep for 1 second
// after each deposit
// Try block to check for exceptions
try {
// Making thread to sleep for 1 second
Thread.sleep(1000);
}
// Catch block to handle InterruptedException
// exception
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// Method - Withdraw
// It is called from ThreadWithdrawal class using
// the object of Bank class passed from the main method
class ThreadWithdrawal extends Thread {
// Attributes of thid class
Bank object;
String name;
int dollar;
// Constructor of this class
ThreadWithdrawal(Bank ob, String name, int money)
{
// This keyword refers to parent class
this.object = ob;
this.name = name;
this.dollar = money;
}
// run() method for the thread
public void run() { object.withdrawn(name, dollar); }
}
// Deposit method is called from ThreadDeposit class using
// the object of Bank class passed from the main method*/
// Class 2
// Helper classs extending Thread class
class ThreadDeposit extends Thread {
Bank object;
String name;
int dollar;
ThreadDeposit(Bank ob, String name, int money)
{
this.object = ob;
this.name = name;
this.dollar = money;
}
public void run() { object.deposit(name, dollar); }
}
// Class 3
// Main class
class GFG {
// Main driver method
public static void main(String[] args)
{
// Declaring an object of Bank class and passing the
// object along with other parameters to the
// ThreadWithdrawal and ThreadDeposit class. This
// will be required to call withdrawn and deposit
// methods from those class
// Creating object of above class inside main()
Bank obj = new Bank();
// Creating threads
ThreadWithdrawal t1
= new ThreadWithdrawal(obj, "Arnab", 20);
ThreadWithdrawal t2
= new ThreadWithdrawal(obj, "Monodwip", 40);
ThreadDeposit t3
= new ThreadDeposit(obj, "Mukta", 35);
ThreadWithdrawal t4
= new ThreadWithdrawal(obj, "Rinkel", 80);
ThreadWithdrawal t5
= new ThreadWithdrawal(obj, "Shubham", 40);
// When a program calls the start() method, a new
// thread is created and then the run() method is
// executed
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
输出:
现在,如果 Shubham 和 Monodwip 未能取款
C:\Users\USER\Desktop\Network Java>javac a.java
C:\Users\USER\Desktop\Network Java>java a
Arnab withdrawn 20
Balance after withdrawal: 80
Rinkel withdrawn 80
Balance after withdrawal: 0
Shubham you can not withdraw 40
your balance is: 0
Mukta deposited 35
Balance after deposit: 35
Monodwip you can not withdraw 40
your balance is: 35
输出(解释): Rinkel 提款失败。
C:\Users\USER\Desktop\Network Java>java a
Arnab withdrawn 20
Balance after withdrawal: 80
Shubham withdrawn 40
Balance after withdrawal: 40
Monodwip withdrawn 40
Balance after withdrawal: 0
Mukta deposited 35
Balance after deposit: 35
Rinkel you can not withdraw 80
your balance is: 35
输出(解释): Monodwip 提款失败。
C:\Users\USER\Desktop\Network Java>java a
Arnab withdrawn 20
Balance after withdrawal: 80
Rinkel withdrawn 80
Balance after withdrawal: 0
Shubham you can not withdraw 40
your balance is: 0
Monodwip you can not withdraw 40
your balance is: 0
Mukta deposited 35
Balance after deposit: 35
Note: The thread scheduler chooses the order of execution of the threads. As it is a random process the output is different for each interpretation.