并发编程Java线程



我已经为课程做了一项任务,但是我们只在一定程度上被教导,这留下了知识差距。我们被要求完成剩余的代码到我们在课堂上所做的某些代码,导师对需要做什么但不做什么,以及自上次做任何独立的Java工作的时间大约7个月,所以我是下面有些生锈的是我们在辅导员指导下编写的代码,而在任务描述下方。

public class CardHolder implements Runnable {
private int id;
private Account account;
final static int numIterations = 20;
public CardHolder(int id, Account account) {
    this.id = id;
    this.account = account;
}
/*
 * run method is what is executed when you start a Thread that
 * is initialised with an instance of this class.
 * You will need to add code to keep track of local balance (cash
 * in hand) and report this when the thread completes.
 */
public void run() {
    for (int i = 0; i < numIterations; i++) {
        // Generate a random amount from 1-10
        int amount = (int)(Math.random()*10)+1;
        // Then with 50/50 chance, either deposit or withdraw it
        if (Math.random() > 0.5) {
            account.withdraw(id, amount); 
        } else {
            account.deposit(id, amount); 
        }
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } 
    }
    System.out.println("THREAD "+ id + " finished"); 
}
}
import java.util.ArrayList;
public class Account {
private String name;
/**
 * @param args
 */
public static void main(String[] args) {
    // Check to make sure program has been called with correct number of
    // command line arguments
    if (args.length != 3) {
        System.err.println("Error: program should take exactly three command line arguments:");
        System.err.println("t<No. of accounts> <main acct starting bal.> <backup acct. starting bal.>");
        System.exit(0);
    }
    // And then make sure that those args are all integers
    try {
        int numCards = Integer.parseInt(args[0]);
        Account account = new Account("Main", Integer.parseInt(args[1]));
        Account backup = new Account("Backup", Integer.parseInt(args[2]));
        // Your code to create and manage the threads should go here.
    } catch (NumberFormatException e) {
        System.err.println("All three arguments should be integers");
        System.err.println("t<No. of accounts> <main acct starting bal.> <backup acct. starting bal.>");
    }
}
// Create an account - initalisation goes in here
public Account(String name, int startingBalance) {
}
// Deposit <amount> into the account
public void deposit(int id, int amount) { 
} 
// Withdraw <amount> from the account
public void withdraw(int id, int amount) {
}  
// Print out the statement of transactions
public void printStatement() {
    System.out.println("Account "" + name + "":");
}
}

eclipse中运行config的参数为50 1000 1000

任务

许多银行系统允许多个持卡人访问一个帐户(例如,企业
帐户)。这样的结果是,一个以上的人可以尝试同时从单个帐户中提取或存入钱。如果访问帐户是天真的(忽略并发编程的原则),此
可能导致比赛条件,以及以下欺诈成功的潜力:多个持卡人可能会合并并试图进行计时攻击。在这样的
中攻击,多个持卡人同时从帐户中提取资金,仅一次扣除账户余额。您的任务是编写一个程序(下面的详细规范),该程序将模拟具有多个链接卡的链接链接银行帐户的操作。换句话说,
会有几个人可以访问每个帐户,每个帐户都有自己的卡()。您的计划应演示并发编程的原则,使其成为
上述欺诈不可能成功

任何帮助将不胜感激

谢谢

好吧,您需要担心的主要内容是存款和提取方法。例如:

public class Account {
    public void deposit(int id, int amount) {
        balance += amount;
    }
    public void withdraw(int id, int amount) {
        balance -= amount;
    }
    private int balance;
}

问题是增量/减少操作可能不是原子。在引擎盖下,可能发生了几项操作,而不仅仅是一项操作。例如:

int temp1 = balance;
int temp2 = amount;
int temp3 = temp1 - temp2;
balance = temp3;

如果您同时执行此操作有很多线程,则可能导致您不需要的结果。尝试考虑原因。您可以使用同步关键字来避免这种情况,这迫使整个方法在原子上执行。我认为它的作用是将类的实例变成 Mutex

public class Account {
    public synchronized void deposit(int id, int amount) {
        balance += amount;
    }
    public synchronized void withdraw(int id, int amount) {
        balance -= amount;
    }
    private int balance;
}

为了对此进行测试,我不会使用随机,因为它不是确定性。我要做的是启动说,1000个线程同时执行特定数量的提款。如果您的余额为$ 1,000,000,并且启动了1000个线程以在1000次以上提取$ 1,则在测试后您的帐户中应该有$ 0。在添加同步关键字之前,请尝试模拟错误的答案,并通过添加同步关键字来验证它是修复的。

最新更新