import edu.mit.ai.psg.traveler.*;
import edu.mit.ai.psg.ui.outliner.*;
import edu.mit.ai.psg.jexa.*;
import java.lang.reflect.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
public class SharedAccountBioNoInner {
public static void main(String[] ignore) {
final Account account = new Account("MyChecking", 0);
Thread billee = new BilleeThread("Billee", account);
Thread lordy = new LordyThread("Lordy", account);
System.err.println("yearLength = "+yearLength);
System.err.println("monthLength = "+monthLength);
System.err.println("weekLength = "+weekLength);
System.err.println("yearStart = "+yearStart);
System.err.println("yearEnd = "+yearEnd);
billee.start();
lordy.start();
try { billee.join(); lordy.join(); } catch (InterruptedException e) {}
System.out.println(account.getBalance());
return;
}
static void sleepTo(long wakeupTime) {
long now = System.currentTimeMillis();
System.err.println(Thread.currentThread().getName()+
" sleeping "+(wakeupTime - now)+"ms");
if (wakeupTime > now) {
try { Thread.sleep(wakeupTime - now); }
catch (InterruptedException e) {}
catch (IllegalArgumentException e) { } } else Thread.yield();
}
static final int yearLength = 24000; static final int monthLength = yearLength/12;
static final int weekLength = yearLength/52;
static long yearStart = System.currentTimeMillis();
static long yearEnd = yearStart + yearLength;
}
class BilleeThread extends Thread {
Account account;
public BilleeThread(String name, Account account) {
super(name);
this.account = account;
}
public void run() {
System.err.println("Billee weekLength = "+weekLength);
System.err.println("Billee yearStart = "+yearStart);
int salary = 300;
for (int week = 1; week <= 52; week++) {
Trace.doing(new StringRecord("...Sleeping to work..."));
SharedAccountBioNoInner.sleepTo(yearStart + week * weekLength);
account.deposit(salary);
}
}
static final int weekLength = SharedAccountBioNoInner.weekLength;
static final long yearStart = SharedAccountBioNoInner.yearStart;
}
class LordyThread extends Thread {
Account account;
LordyThread(String name, Account account) {
super(name);
this.account = account;
}
public void run() {
System.err.println("Lordy monthLength = "+monthLength);
System.err.println("Lordy weekLength = "+weekLength);
System.err.println("Lordy yearStart = "+yearStart);
System.err.println("Lordy yearEnd = "+yearEnd);
int rent = 1000; int penalty = 10;
Collection outstandingCollectors =
Collections.synchronizedCollection(new LinkedList());
int collectorCount = 0; for (int month = 1; month <= 12; month++) {
try { account.withdraw(rent); }
catch (IllegalArgumentException overdraft) {
Thread collector =
new CollectorThread("Collector"+(++collectorCount),
account, rent + penalty, penalty,
outstandingCollectors);
collector.start();
Thread.yield();
}
Trace.doing(new StringRecord
(outstandingCollectors.isEmpty()?
"...sweet dreams..." : "...fitful naps ..."));
SharedAccountBioNoInner.sleepTo(yearStart + month * monthLength);
}
return;
}
static final int monthLength = SharedAccountBioNoInner.monthLength;
static final int weekLength = SharedAccountBioNoInner.weekLength;
static final long yearStart = SharedAccountBioNoInner.yearStart;
static final long yearEnd = SharedAccountBioNoInner.yearEnd;
}
class CollectorThread extends Thread {
Account account;
int due;
int penalty;
long startDate = System.currentTimeMillis();
Collection outstandingCollectors;
CollectorThread(String name, Account account, int amountDue,
int penalty, Collection outstandingCollectors){
super(name);
this.account = account;
this.due = amountDue;
this.penalty = penalty;
this.outstandingCollectors = outstandingCollectors;
}
public void run() {
outstandingCollectors.add(this);
int week = 0;
while (System.currentTimeMillis() <= yearEnd) {
try {
account.withdraw(due);
break;
} catch (IllegalArgumentException overdraft2) {
week++; due += penalty;
Trace.doing(new StringRecord("...snoring..."));
SharedAccountBioNoInner.sleepTo(startDate + week * weekLength);
}
}
outstandingCollectors.remove(this);
return;
}
static final long weekLength = SharedAccountBioNoInner.weekLength;
static final long yearEnd = SharedAccountBioNoInner.yearEnd;
}
class Account implements Cloneable {
private String myName;
private int myBalance;
public Account(String name, int initBalance) {
myName = name;
myBalance = initBalance;
}
public synchronized int getBalance() {
return myBalance;
}
public synchronized void deposit(int amount) {
myBalance += amount;
}
public synchronized void withdraw(int amount) {
if (amount <= myBalance)
myBalance -= amount;
else
throw new IllegalArgumentException("Overdraft");
}
public String toString() {
return "Account(name="+myName+", balance="+myBalance+")"; }
}