-2

Note: Thread no 1 = Owner 1 -> perform 10 transactions
Thread no 2 = Owner 2 -> perform 10 transactions

Problem: in Output:

Owner: 1   transaction: 2
Owner: 1   transaction: 1
credit: $46 credit: $30  balance: $146
 balance: $130

After Transaction 2 the balance should be $176. There must be some problem in thread pooling. I tried a lot but could not reach the desired solution. Any help would be appreciable.

Output

     run:
    Initial Balance: $100
    Owner: 1   transaction: 1
    Owner: 1   transaction: 2
    credit: $46 credit: $30  balance: $146
     balance: $130
    Owner: 2   transaction: 1
    Owner: 2   transaction: 2
     debit: $46 debit: $30 Debit Done    Debit Done  Balance: $100 Balance: $100
    Owner: 1   transaction: 3
    credit: $75 Owner: 1   transaction: 4
     balance: $175
    credit: $47 Owner: 2   transaction: 3
     balance: $147
    Owner: 2   transaction: 4
     debit: $47 debit: $75 Debit Done    Debit Done  Balance: $100 Balance: $100
    Owner: 1   transaction: 5
    credit: $57 Owner: 1   transaction: 6
     balance: $157
    credit: $13 Owner: 2   transaction: 5
     balance: $113
     debit: $57 Debit Done  Owner: 2   transaction: 6
     Balance: $100 debit: $13 Debit Done     Balance: $100 Owner: 1   transaction: 7
    credit: $84 Owner: 1   transaction: 8
     balance: $184
    credit: $95 Owner: 2   transaction: 7
     balance: $195
    Owner: 2   transaction: 8
     debit: $84 Debit Done   debit: $95 Debit Done   Balance: $100 Balance: $100
    Owner: 1   transaction: 10    credit: $96    balance: $196
    Owner: 1   transaction: 9
    Owner: 2   transaction: 10
    credit: $20  debit: $96 Debit Done   balance: $120
     Balance: $100
    Owner: 2   transaction: 9
    debit: $20 Debit Done    Balance: $100B

Bank

public class Bank{

private BankAccount bankAccount = new BankAccount(100);

public void displayInitialBalance(){
    System.out.println("Initial Balance:"+getBankAccount());
}

/**
 * @return the bankAccount
 */
public BankAccount getBankAccount() {
    return bankAccount;
}

/**
 * @param bankAccount the bankAccount to set
 */
public void setBankAccount(BankAccount bankAccount) {
    this.bankAccount = bankAccount;
}

public static void main(String[] args){
    BankAccount bankAccount = new BankAccount(100);
    System.out.println("Initial Balance: $"+bankAccount.getCurrentBalance());
    ExecutorService executorService = Executors.newFixedThreadPool(2);
    for(int count = 1; count<=10; count++){
        Runnable runnable = new Owner(count);
        executorService.execute(runnable);
    }
    executorService.shutdown();
    while(!executorService.isTerminated()){
    }
    System.out.println("All Transactions Done");
}

}


BankAccount

public class BankAccount {

private int currentBalance;

public BankAccount(int initialBalance){
    this.currentBalance = initialBalance;
}

synchronized public void credit(int amount){
    setCurrentBalance(currentBalance + amount);
    System.out.print("credit: $"+amount+"\t");
    System.out.println(" balance: $"+getCurrentBalance());
}

synchronized public void debit(int amount){
    if(getCurrentBalance() >= amount){
        setCurrentBalance(currentBalance - amount);
        System.out.print(" debit: $"+amount);
        System.out.print(" Debit Done" +"\t");                
        System.out.print(" Balance: $"+getCurrentBalance());            
    }
    else{
        System.out.print("Insufficient Balance"+"\t");
        System.out.println("Balance: $"+getCurrentBalance());
    }
}

/**
 * @return the currentBalance
 */
public int getCurrentBalance() {
    return currentBalance;
}

/**
 * @param currentBalance the currentBalance to set
 */
public void setCurrentBalance(int currentBalance) {
    this.currentBalance = currentBalance;
}
}    


Owner

public class Owner implements Runnable{

public int transactionCount = 0;
public int amount = 0;

private BankAccount bankAccount = new  BankAccount(100);

public Owner(int transactionCycle){
    this.transactionCount = transactionCycle;
}

public Owner(int transactionId, BankAccount bankAccount){
    this.bankAccount = bankAccount;
    this.transactionCount = transactionId;
}

@Override
public void run() {
   try{
       amount = (int)(Math.random() * 100 + 10);
       Thread call = new Thread();
       call.start();
       Thread.currentThread().setName("Owner: 1 "+"  transaction: "+transactionCount);
       (transactionCount)++;
       System.out.println(Thread.currentThread().getName());
       getBankAccount().credit(amount);
       Thread.currentThread().setName("Owner: 2 "+"  transaction: "+ --(transactionCount));
       (transactionCount)++;
       System.out.println(Thread.currentThread().getName());
       getBankAccount().debit(amount);
   }catch(UnsupportedOperationException e){
       e.printStackTrace();
   } 

}

/**
 * @return the bankAccount
 */
public BankAccount getBankAccount() {
    return bankAccount;
}

/**
 * @param bankAccount the bankAccount to set
 */
public void setBankAccount(BankAccount bankAccount) {
    this.bankAccount = bankAccount;
}

}
Jaap
  • 81,064
  • 34
  • 182
  • 193
noman
  • 37
  • 2
  • 14
  • You have a class `Bank` that you never instantiate, uncompilable code, a `Thread call` that does nothing, and insufficient synchronization even if you were running that code in different threads. The `BankAccount` instances are never directly accessed from multiple threads, but it's partially (!) synchronized, and the `Owner` instances _are_ accessed from multiple threads (or would be), but it does not have synchronized methods. Among other things (like fixing the compiler errors), I suggest making the `Owner#bankAccount ` `final` and set on construction. Not twice as it is now. – Lew Bloch Feb 19 '17 at 04:00
  • You are right about Thread call, & i have removed it. But the thing i did not understand is, I changed `BankAccount instance` to final and call it from `Constructor` once but the synchronization still works wrong `private final BankAccount bankAccount; public Bank(){ bankAccount = new BankAccount(100); }` – noman Feb 19 '17 at 05:00
  • Now all code works fine, performing correct computations just one issue arises in `output format` `Owner: 1 transaction: 1 credit: $10 Balance: $110 Owner: 2 transaction: 1 debit: $48 Debit Done` **??** `Owner: 1 transaction: 2 Balance: $62 credit: $88 Balance: $150 Owner: 2 transaction: 2 debit: $85 Debit Done Balance: $65` **Where i put **??** `Balance $62` has to print on there – noman Feb 19 '17 at 06:07
  • 1
    _"There must be some problem in thread pooling"_ -- extremely unlikely, more likely the problem is in _your_ code. Please visit the [help], read [ask] and also read [Why is “Can someone help me?” not an actual question?](http://meta.stackoverflow.com/q/284236/18157) – Jim Garrison Feb 19 '17 at 06:16
  • I am trying myself too to find the solution. – noman Feb 19 '17 at 06:26

2 Answers2

0

You are creating new Owner instances in Bank.main() without passing BankAccount hence each Owner object is operating on different BankAccount instances

Ashwin
  • 115
  • 1
  • 6
  • `Runnable runnable = new Owner(count,bankAccount);` after providing bankAccount as parameter in `Owner()` code works fine. But the output format would be distrurb as `output` is `Owner: 1 transaction: 1 Owner: 1 transaction: 2 credit: $49 balance: $149 credit: $29 ` `Owner: 2 transaction: 1 balance: $178 Owner: 2 transaction: 2 debit: $87 Debit Done Balance: $91 debit: $24 Debit Done Balance: $67` – noman Feb 19 '17 at 05:39
  • ** Output Should be like this** `Owner: 1 transaction: 1 Owner: 1 transaction: 2 credit: $49 balance: $149 credit: $29 balance: $178` So there must be some issue which i try a lot could not catch is of synchronization – noman Feb 19 '17 at 05:40
0

Done a lot of tries in and atlast got the required output

Changes done

BankAccount

private int currentBalance = 0; // set default value of int
public void credit(int amount){
    System.out.print(" credit: $"+amount+"\t");
}

public Boolean debit(int amount){
    if(getCurrentBalance() >= amount){
        return true;
    }
    else
        return false;
}

Bank
How to wait for all threads to finish, using ExecutorService?

Inside for loop of main method

Runnable runnable = new Owner(id,bankAccount);
bankAccount.getCurrentBalance(); // To print each thread transaction balance
try {
        executorService.awaitTermination(Long.MAX_VALUE,  TimeUnit.NANOSECONDS); // instead of Terminate use awaitTermination method for each thread 
    } catch (InterruptedException e) {
        e.printStackTrace();
    }    

Owner

try{
       amount = (int)(Math.random() * 100 + 10);
       Thread.currentThread().setName(" Owner: 1 "+"  transaction: "+transactionCount);
       (transactionCount)++;
       System.out.print(Thread.currentThread().getName()+"\n");
       getBankAccount().credit(amount);
       bankAccount.setCurrentBalance(getBankAccount().getCurrentBalance() + amount);
       System.out.print("Balance: $"+bankAccount.getCurrentBalance());
       amount = (int)(Math.random() * 100 + 10);
       Thread.currentThread().setName(" Owner: 2 "+"  transaction: "+ --(transactionCount));
       System.out.print(Thread.currentThread().getName()+"\n");
       (transactionCount)++;
       getBankAccount().getCurrentBalance();
       Boolean isDebit = getBankAccount().debit(amount);
       if(isDebit){
           try {
                bankAccount.setCurrentBalance(getBankAccount().getCurrentBalance() - amount);
                System.out.println(" debit: $"+amount);
                System.out.print(" Debit Done" +"\t");
                System.out.println(" Balance: $"+bankAccount.getCurrentBalance());
           } catch (SecurityException ex) {
                Logger.getLogger(Owner.class.getName()).log(Level.SEVERE, null, ex);
           }
        }else{
                System.out.println("Insufficeint Balance");
        }

   }catch(UnsupportedOperationException e){
       e.printStackTrace();
   } 
Community
  • 1
  • 1
noman
  • 37
  • 2
  • 14
  • Your BankAccount#credit and debit methods do not alter the balance. Your Bank class is not used by anything else you show us. You're using Boolean where you should use boolean to declare an unnecessary variable. You've got unrelated BankAccount instances referenced by different class's instances. You change thread names arbitrarily and frequently for no engineering purpose. You're not showing that Owner methods are synchronized. You spelled "Insufficient" wrong. You use \n in a print instead of just println. .. – Lew Bloch Feb 19 '17 at 10:35
  • Credit & Debit methods alter the balance two transaction output attached `Initial Balance:$100 Owner: 1 transaction: 2 credit: $38 Balance: $138 Owner: 2 transaction: 2 debit: $79 Debit Done Balance: $59 Owner: 1 transaction: 3 credit: $35 Balance: $94 Owner: 2 transaction: 3 debit: $39 Debit Done Balance: $55` – noman Feb 19 '17 at 11:15
  • Yes I believe that some how my approach is not perfect in changing threads is not good but the remaining \n instead of println that is just used to format of my output. In starting i have synchronized the **debit()** & **credit methods** but they are not working, so i try to work without it & that works. – noman Feb 19 '17 at 11:21