简体   繁体   中英

Using thread pool synchronization bank java

I want to make a simple bank using thread in Java. But I can't make deposit(), withdraw() to synchronize. There is not synchronized balance all the time. I write 'synchronized' keyword in the method name, but it never works. Also, I make 'synchronizedList' in my ArrayList (I should use array list to make this) but it never works. How can I get an appropriate balance? please help me.

import java.security.SecureRandom;

public class Transaction implements Runnable {
    
    private static final SecureRandom generator = new SecureRandom();
    private final int sleepTime; // random sleep time for thread
    private String transaction;
    private int amount;
    private static int balance;
    private Account account = new Account();
    
    public Transaction (String transaction, int amount) {
        this.transaction = transaction;
        this.amount = amount;
        sleepTime = generator.nextInt(2000); 
    }
    
    @Override
    public void run() {
        // TODO Auto-generated method stub
        try {
            if(transaction == "deposit") {
                balance = account.deposit(amount);

            } else if (transaction == "withdraw") {
                balance = account.withdraw(amount);
            }
            
            System.out.println("[" + transaction + "] amount : " + amount +" balance : " + balance);
            Thread.sleep(sleepTime);
            
        }catch (InterruptedException e) {
            e.printStackTrace();
             Thread.currentThread().interrupt(); // re-interrupt the thread
        }

    }

}

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class AccountTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        // create ArrayList
        List<Transaction> john = Collections.synchronizedList(new ArrayList<>());
        
        // add Transaction objects
        john.add(new Transaction("deposit", 1000));
        john.add(new Transaction("withdraw", 500));
        john.add(new Transaction("withdraw", 200));
        john.add(new Transaction("deposit", 3000));

        // execute Thread Pool
        ExecutorService executorService = Executors.newCachedThreadPool();
        
        // start transactions
        for(int i=0; i<john.size(); i++) {
            executorService.execute(john.get(i)); 
        }
        
        // shut down Thread Pool
    }
}

public class Account {
// deposit withdraw
    private static int balance;
    
    public synchronized int deposit(int amount) {
        balance += amount;
        return balance;
    }
    
    public synchronized int withdraw(int amount) {
        balance -= amount;
        return balance;
    }
}

The core mistake here is that each Transaction has its own Account. Each thread is acquiring the lock on its own instance of Account, with the result that there is no actual locking going on.

You need a lock that is shared between the threads, they need to be trying to modify the same Account object. Instance methods marked with synchronized acquire a lock baked into the object instance.

Making the balance on Account static is a dirty hack that makes all the balance data end up in the same place (which works only as long as you have only one Account) but doesn't address the synchronization problem.

(You could change the Account methods to be static too, and that would fix the synchronization issue since all the threads would be acquiring the lock on the class, and there is only one class. But of course it stops working once you need a second account so it is not a great solution.)

Rework this so that, instead of having each Transaction create its own account, you share the same Account object across Transactions. You can pass the Account into the Transaction as a constructor argument.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM