Initial commit
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Gradle build configuration for specific lab module / exercise
|
||||
* Default declarations can be found in the lab main build configuration (../../gradle.build)
|
||||
* Declarations in this file extend or override the default values.
|
||||
*/
|
||||
// the Java plugin is added by default in the main lab configuration
|
||||
plugins {
|
||||
// Apply the application plugin to add support for building a CLI application.
|
||||
id 'application'
|
||||
}
|
||||
|
||||
description = 'Lab04 AccountTransfer Solution'
|
||||
|
||||
dependencies {
|
||||
|
||||
}
|
||||
|
||||
// Configuration for Application plugin
|
||||
application {
|
||||
// Define the main class for the application.
|
||||
mainClass = 'ch.zhaw.prog2.account.AccountTransferSimulation'
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package ch.zhaw.prog2.account;
|
||||
|
||||
public class Account {
|
||||
private final int id;
|
||||
private int balance = 0;
|
||||
|
||||
public Account(int id, int initialAmount) {
|
||||
this.id = id;
|
||||
this.balance = initialAmount;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public synchronized int getBalance() {
|
||||
return balance;
|
||||
}
|
||||
|
||||
public synchronized void transferAmount(int amount) {
|
||||
this.balance += amount;
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
package ch.zhaw.prog2.account;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class AccountTransferSimulation {
|
||||
|
||||
private static final int ITERATIONS = 10000;
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
|
||||
Account account1 = new Account(1, 10);
|
||||
Account account2 = new Account(2, 10);
|
||||
Account account3 = new Account(3, 999999);
|
||||
|
||||
System.out.println("Start Balance:");
|
||||
System.out.println("- Account1 = " + account1.getBalance());
|
||||
System.out.println("- Account2 = " + account2.getBalance());
|
||||
System.out.println("- Account3 = " + account3.getBalance());
|
||||
System.out.println("Summed up balances of all accounts: " +
|
||||
(account1.getBalance() + account2.getBalance() + account3.getBalance()));
|
||||
System.out.println("Start of Transaction");
|
||||
|
||||
// AccountTransferTask task1 = new AccountTransferTask(account3, account1, 2);
|
||||
AccountTransferTask task1 = new AccountTransferTask(account1, account3, 2);
|
||||
AccountTransferTask task2 = new AccountTransferTask(account3, account2, 1);
|
||||
AccountTransferTask task3 = new AccountTransferTask(account2, account1, 2);
|
||||
|
||||
// create ExecutorService
|
||||
ExecutorService executor = Executors.newFixedThreadPool(8);
|
||||
|
||||
// execute transactions on accounts
|
||||
System.out.println("Submitting...");
|
||||
for (int count = 0; count < ITERATIONS; count++) {
|
||||
executor.execute(task1);
|
||||
executor.execute(task2);
|
||||
executor.execute(task3);
|
||||
}
|
||||
System.out.println("Working...");
|
||||
|
||||
executor.shutdown();
|
||||
// wait for completion
|
||||
boolean completed = executor.awaitTermination(20, TimeUnit.SECONDS);
|
||||
|
||||
if (completed) {
|
||||
System.out.println("Transactions completed!");
|
||||
} else {
|
||||
System.out.println("Transactions timed out!");
|
||||
executor.shutdownNow();
|
||||
|
||||
}
|
||||
|
||||
// Print end statistics
|
||||
System.out.println("Amount transferred (when enough on fromAccount):");
|
||||
System.out.println("- Task 1 = " + task1.getTotalTransfer());
|
||||
System.out.println("- Task 2 = " + task2.getTotalTransfer());
|
||||
System.out.println("- Task 3 = " + task3.getTotalTransfer());
|
||||
System.out.println("End Balance:");
|
||||
System.out.println("- Account1 = " + account1.getBalance());
|
||||
System.out.println("- Account2 = " + account2.getBalance());
|
||||
System.out.println("- Account3 = " + account3.getBalance());
|
||||
System.out.println("Summed up balances of all accounts (should be the same as at start): " +
|
||||
(account1.getBalance() + account2.getBalance() + account3.getBalance()));
|
||||
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
package ch.zhaw.prog2.account;
|
||||
|
||||
class AccountTransferTask implements Runnable {
|
||||
|
||||
private final Account fromAccount;
|
||||
private final Account toAccount;
|
||||
private final int amount;
|
||||
private int totalTransfer = 0;
|
||||
|
||||
public AccountTransferTask(Account fromAccount, Account toAccount, int amount) {
|
||||
this.fromAccount = fromAccount;
|
||||
this.toAccount = toAccount;
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public int getTotalTransfer() {
|
||||
return this.totalTransfer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
//transfer();
|
||||
transferDLfree();
|
||||
}
|
||||
|
||||
/* b) ensure no lost updates are happening */
|
||||
public void transfer() {
|
||||
synchronized (fromAccount) {
|
||||
synchronized (toAccount) {
|
||||
// Account must not be overdrawn
|
||||
if (fromAccount.getBalance() >= amount) {
|
||||
fromAccount.transferAmount(-amount);
|
||||
toAccount.transferAmount(amount);
|
||||
totalTransfer += amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* c) deadlock free using ascending order of IDs */
|
||||
public void transferDLfree() {
|
||||
// This implementation is deadlock free using the second possibility
|
||||
// -> locking of accounts in ascending order of accountID
|
||||
boolean isLower = fromAccount.getId() < toAccount.getId();
|
||||
Account lowerAccount = isLower ? fromAccount : toAccount;
|
||||
Account higherAccount = !isLower ? fromAccount : toAccount;
|
||||
synchronized (lowerAccount) {
|
||||
synchronized (higherAccount) {
|
||||
// Account must not be overdrawn
|
||||
if (fromAccount.getBalance() >= amount) {
|
||||
fromAccount.transferAmount(-amount);
|
||||
toAccount.transferAmount(amount);
|
||||
totalTransfer += amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user