在多个线程上访问和编辑全局字段

时间:2017-05-02 02:18:22

标签: java multithreading runnable

我正在尝试使用多线程模拟单个银行帐户上的两个用户,撤回并存入资金。我希望两个用户对单个共享变量进行操作,当然代表帐户余额。

存款或取款的行为是随机选择的 - 1或2(分别存款和取款)。存款时,我希望存款操作需要1秒钟,撤销操作需要0.5秒。在此时间间隔内,线程必须等待另一个线程完成操作才能撤回/存放自己。

然而,我最大的问题是两个线程如何编辑单个共享数字字段,即余额。我第一次尝试时,每个线程都创建了自己的余额实例,并分别对它们进行了操作。我希望每个线程的操作(撤销/存款)影响全局字段“平衡” - 而不是实例字段。

我到目前为止构建的线程类和Driver类。

线程创建者类:

public class BankAccountSim extends Thread{
public double balance = 1000;
public String threadName;

BankAccountSim(String name){
    threadName = name;
}
public void run(){
    System.out.println(threadName + "account initiated.");
    while(true){
        try{
            Random rand = new Random();
            int num = rand.nextInt(2) + 1;
            if(num == 1){
                System.out.println(threadName + " is depositing in the bank.");
                balance += 1;
                System.out.println("The new balance is " + balance + " dollars" );
                Thread.sleep(1000);
                Thread.yield();
            }
            else{
                System.out.println(threadName + " is withdrawing from the bank.");
                balance -= 1;
                System.out.println("The new balance is " + balance + " dollars.");
                Thread.sleep(500);
                Thread.yield();
                }
        }

        catch(InterruptedException e){
            System.out.println("Process terminated.");
            }
        }
    }
}

线程驱动程序类:

import java.util.concurrent.ThreadLocalRandom;
import java.util.Random;

public class BankAccountSimDriver {
    public static void main(String[] args){

    Thread user1 = new BankAccountSim("user1");
    Thread user2 = new BankAccountSim("user2");

    user1.start();
    user2.start();

    }
}

3 个答案:

答案 0 :(得分:0)

这主要是一个设计问题。您最好创建一个银行帐户并与客户共享,就像在现实世界中一样。

interface BankAccount {
    // Query the balance
    BigDecimal balance();

    // Make a deposit and return the new balance
    BigDecimal deposit(BigDecimal amount);

    // Make a withdrawal and return the new balance
    BigDecimal withdraw(BigDecimal amount);
}

// Implements the Runnable interface for run in another thread.
class BankClient implements Runnable {
    private final String clientName;

    private final BankAccount bankAccount;

    public BankClient(String clientName, BankAccount bankAccount) {
        this.clientName = clientName;
        this.bankAccount = bankAccount;
    }

    public void run() {
        // while(true) ...
    }
}

class SimpleBankAccount implements BankAccount {
    private BigDecimal balance = BigDecimal.ZERO;

    public SimpleBankAccount(BigDecimal initialBalance) {
        this.balance = initialBalance;
    }

    public synchronized BigDecimal balance () {
        return balance;
    }

    public synchronized BigDecimal deposit(BigDecimal amount) {
        return balance = balance.add(amount);
    }

    public synchronized BigDecimal withdraw(BigDecimal amount) {
        if (balance.compareTo(amount) < 0) {
            throw new RuntimeException("Not enough balance.");
        }
        return balance = balance.subtract(amount);
    }
}

public class SimDriver {
    public static void main(String[] args) throws Exception {
        BankAccount account = new SimpleBankAccount(BigDecimal.valueOf(1000));

        Thread t1 = new Thread(new BankClient("client-1", account));
        thread t2 = new Thread(new BankClient("client-2", account));

        t1.start();
        t2.start();

        t1.join();
        t2.join();
    }
}

答案 1 :(得分:0)

有趣的是,你想要一个自己的线程,但是,不要认为with open("file.txt") as myFile: for strLine in myFile: if "item" not in strLine: continue for strLine in myFile: #using same counter as outer loop processitemdata() # Should you test for ">" first? if ">" in strLine: break 是一个线程,Action是一个线程。关于这个设计的一点说明。我个人的经验法则是我只使用BankAccount作为原始类型。如果您将volatile更改为balance或其他对象,请锁定Double或使用Object或其他内容。

AtomicReference

答案 2 :(得分:0)

一个简单的解决方案是通过更改:{/ p>来平衡AtomicInteger

public double balance = 1000;

public AtomicInteger balance = new AtomicInteger(1000);

然而,您需要稍微修改更新余额的方式,例如添加到余额中:

balance.addAndGet(1);