Reputation: 67
I am working on a project and i have two threads that run together. The project is a mock bank, and essentially, we have a deposit thread and a withdraw thread. I am having an issue with the deposit threads running to often, and causing the balance of the bank account to rise. (I wish i had this issue in real iife.) How can i reduce the time a thread runs?
Here is my main class:
package bankexample;
import bankexample.depositThread;
public class BankExample {
public static int balance =0 ;
public static void main(String[] args) {
System.out.println("Deposit Thread Withdrawl Thread Balance \n");
System.out.println("-------------- ----------------- --------");
while (true){
Thread d1 = new Thread(new depositThread(1));
Thread d2 = new Thread(new depositThread(2));
Thread d3 = new Thread(new depositThread(3));
Thread w1 = new Thread(new WithdrawThread(1));
Thread w2 = new Thread(new WithdrawThread(2));
Thread w3 = new Thread(new WithdrawThread(3));
Thread w4 = new Thread(new WithdrawThread(4));
d1.start();
d2.start();
d3.start();
w1.start();
w2.start();
w3.start();
w4.start();
}
}
}
Here are the withdraw and deposit thread classes:
package bankexample;
/**
*
* @author KJ4CC
*/
public class WithdrawThread implements Runnable {
transaction withdraw = new transaction();
int threadNum;
public WithdrawThread(int num){
threadNum = num;
}
public void run(){
withdraw.withdraw(threadNum);
}
}
---------------------------
package bankexample;
import bankexample.transaction;
/**
*
* @author KJ4CC
*/
public class depositThread implements Runnable {
transaction startThread = new transaction();
public static int balance;
int threadNum;
public depositThread(int num){
threadNum = num;
}
@Override
public void run(){
try {
Thread.sleep(100);
startThread.deposit(threadNum);
} catch (Exception e) {
}
}
}
and finally her is the transaction class:
package bankexample;
import java.util.Random;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.Condition;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author KJ4CC
*/
public class transaction extends BankExample {
private Lock accessLock = new ReentrantLock();
private Condition cond = accessLock.newCondition();
private boolean occupied = false;
Random rand = new Random();
public void deposit(int threadNum) throws InterruptedException{
//random amount for amount to deposit into bank mod 200
int amount = rand.nextInt(200);
//locks the thread
//System.out.println("Balance before Deposit " + balance);
accessLock.lock();
try {
//System.out.println(getBalance.getbalance());
//adds the amount to the balance.
if (occupied == false){
occupied = true;
balance = (balance + amount);
//outputs to terminal
System.out.println("Thread " + threadNum + " Deposits " + amount + "\t\t\t\t Balance is " + balance);
occupied = false;
Thread.sleep(10000);
//signals any awiting widthdraw threads
cond.signal();
}
} finally {
//unlocks thread
accessLock.unlock();
}
}
public void withdraw(int threadNum){
//getting a random amount mod50
int amount = rand.nextInt(50);
//locking the thread
accessLock.lock();
try {
//test print out
//checks to see if the amount is less than the balance
if (amount < balance && occupied == false) {
occupied = true;
// System.out.println("Balance before withdraw " + balance);
balance = (balance - amount );
System.out.println("\t\t\tThread " + threadNum + " withdrawls " + amount + "\t Balance is " + balance);
cond.signalAll();
occupied = false;
//if it isnt we can not make a withdraw so we have to wait for a deposit
} else {
System.out.println("\t\t\tThread " + threadNum + " Failed to withdrawl " + amount + "\t Balance is " + balance);
cond.await();
}
//unlock the thread
} catch (InterruptedException ex) {
Logger.getLogger(transaction.class.getName()).log(Level.SEVERE, null, ex);
} finally {
accessLock.unlock();
}
}
}
I have tried to have the threads sleep before they hit the lock condition, but unfortunately, it doesn't work.
Here is a sample from the output:
Deposit Thread Withdrawl Thread Balance
-------------- ----------------- --------
Thread 1 Failed to withdrawl 4 Balance is 0
Thread 2 Failed to withdrawl 49 Balance is 0
Thread 3 Failed to withdrawl 21 Balance is 0
Thread 4 Failed to withdrawl 13 Balance is 0
Thread 1 Failed to withdrawl 30 Balance is 0
Thread 2 Failed to withdrawl 15 Balance is 0
Thread 3 Failed to withdrawl 18 Balance is 0
Thread 4 Failed to withdrawl 25 Balance is 0
Thread 2 Failed to withdrawl 27 Balance is 0
Thread 1 Failed to withdrawl 9 Balance is 0
Thread 3 Failed to withdrawl 0 Balance is 0
Thread 4 Failed to withdrawl 21 Balance is 0
Thread 1 Failed to withdrawl 31 Balance is 0
Thread 2 Failed to withdrawl 32 Balance is 0
Thread 3 Failed to withdrawl 47 Balance is 0
Thread 4 Failed to withdrawl 8 Balance is 0
Thread 1 Failed to withdrawl 22 Balance is 0
Thread 2 Failed to withdrawl 38 Balance is 0
Thread 3 Failed to withdrawl 43 Balance is 0
Thread 4 Failed to withdrawl 2 Balance is 0
Thread 1 Failed to withdrawl 19 Balance is 0
Thread 2 Failed to withdrawl 39 Balance is 0
Thread 3 Failed to withdrawl 43 Balance is 0
Thread 4 Failed to withdrawl 48 Balance is 0
Thread 1 Failed to withdrawl 45 Balance is 0
Thread 3 Failed to withdrawl 45 Balance is 0
Thread 2 Failed to withdrawl 25 Balance is 0
Thread 4 Failed to withdrawl 21 Balance is 0
Thread 2 Deposits 188 Balance is 188
Thread 3 Deposits 128 Balance is 316
Thread 2 Deposits 54 Balance is 370
Thread 1 Deposits 123 Balance is 493
Thread 3 Deposits 59 Balance is 552
Thread 1 withdrawls 38 Balance is 514
Thread 2 withdrawls 35 Balance is 479
Thread 3 withdrawls 40 Balance is 439
Thread 4 withdrawls 5 Balance is 434
Thread 1 Deposits 179 Balance is 613
Thread 1 Deposits 108 Balance is 1027
Thread 2 Deposits 56 Balance is 919
Thread 1 Deposits 96 Balance is 863
Thread 2 Deposits 101 Balance is 767
Thread 3 Deposits 149 Balance is 1176
Thread 3 Deposits 53 Balance is 666
Thread 2 Deposits 67 Balance is 1277
Thread 1 Deposits 108 Balance is 1385
Thread 3 Deposits 34 Balance is 1277
Thread 2 Deposits 69 Balance is 1466
Thread 3 Deposits 49 Balance is 1561
Thread 4 withdrawls 32 Balance is 1529
Thread 1 Deposits 12 Balance is 1561
Thread 2 Deposits 46 Balance is 1561
Thread 1 Deposits 99 Balance is 15
Upvotes: 0
Views: 317
Reputation: 313
The bigger issue is that on each iteration of the while(true)
, you are creating 7 separate Threads. You are basically spawning an infinite number of Threads and bank accounts here.
Each time you instantiate a new DepositThread
or WithdrawThread
, you are creating a new transaction
object, each with its own private Lock
that effectively synchronizes nothing.
public class WithdrawThread implements Runnable {
//creates a new Lock per *Thread*
transaction withdraw = new transaction();
...
}
There is no properly-protected shared state among any of your threads. Each WithdrawThread
/DepositThread
is only ever attempting to acquire its own private Lock via the transaction
object. A Lock
can only enforce mutual exclusion on a resource if all Threads can access it.
A better solution would be to have one Transaction
object, whose reference is passed as a parameter to each Thread.
Upvotes: 2
Reputation: 8928
It sounds like you intend to have two threads that run at the same time, one deposit thread and one withdrawal thread, but that's not what you have. Rather, your main loop is creating three separate deposit threads and four separate withdrawal threads each time through the loop, and the loop seems to run indefinitely, so you're creating an unlimited number of threads. Since the deposit threads have a 100ms delay and the withdrawal threads don't, a bunch of the withdrawal threads run, then after 100ms a bunch of deposit threads run. In addition, the threads are not actually accessing a common "bank account" balance.
To start with, have the main thread create just one withdrawal thread and one deposit thread, and then exit. Then put the loops in the deposit and withdrawal threads. That will fix some of your problems.
After you've done that, you'll probably still have other problems, but they'll be different problems and you may be able to figure them out and fix them by yourself. If not, you can always post a new question on them.
Upvotes: 1