Variation on Producer / Consumer
Here is a variation on the Producer / Consumer with 4 puts and 4 gets. I don't understand why the notifyall is not causing the Saver thread to awake. I would appreciate any suggestions.
import java.util.*;
public class SpendnSave {
Float Balance = new Float(0); // Account Balance
boolean insufficient_funds;
// Constructor *******************************************************************
public SpendnSave()
{
new Spender().start(); // Spend a little
new Saver().start();// Save a little
}
// Saver *******************************************************************
class Saver extends Thread {
Float Amount;
// Constructor
Saver()
{
super();
this.Amount = 0f;
}
public void run()
{
this.deposit(100f);
this.deposit(200f);
this.deposit(300f);
this.deposit(400f);
}
synchronized void deposit(Float Amount)
{
Balance += Amount;
System.out.println("deposit is:" + Amount);
System.out.println("deposit balance is:" + Balance + " ** " + Thread.currentThread().getName());
if (Balance > 900) {
insufficient_funds = false;
System.out.println("deposit notifying..." + insufficient_funds);
notifyAll();
}
}
} // Saver
// Spender *******************************************************************
class Spender extends Thread {
Float Amount;
// Constructor
Spender()
{
super();
this.Amount = 0f;
}
public void run()
{
this.withdrawal(50f);
this.withdrawal(100f);
this.withdrawal(150f);
this.withdrawal(200f);
}
synchronized void withdrawal (Float Amount)
{
Balance -= Amount;
System.out.println("withdrawal is:" + Amount);
System.out.println("withdrawal balance is:" + Balance + " ** " + Thread.currentThread().getName());
if (Balance < 0) insufficient_funds = true;
// Insufficient Funds.....
while (insufficient_funds)
{
System.out.println("Insufficient Funds...." + Balance);
try {
System.out.println("Thread Waiting....." + insufficient_funds);
wait(); // Relinquish the lock...
// Let the Saver Thread notify when the balance is greater than zero
System.out.println("After Waiting");
}
catch (InterruptedException e)
{
System.out.println("Withdrawal permitted to continue (INTERRUPTED)");
}
insufficient_funds = false;
}
}
}
public static void main(String args[])
{
SpendnSave spendnsave = new SpendnSave();
// Slow up the main thread so we can see how many threads are active...
try {
Thread.sleep(5000);
}
catch (InterruptedException e) {}
System.out.println("Alive Threads:" + Thread.activeCount());
}
}
[2990 byte] By [
skalvia] at [2007-11-27 8:26:58]

# 1
At first sight i would say you are waiting/notifying on "this" in each Thread.Which means on different objects...Try using the same object as lock. (btw think about modify your synchronizes to synchronize on the lock too).
ibanna at 2007-7-12 20:16:34 >

# 2
I tried this variation also without any success.
import java.util.*;
public class SpendSave {
Float Balance = new Float(0); // Account Balance
boolean insufficient_funds;
// Constructor *******************************************************************
public SpendSave()
{
new Spender().start(); // Spend a little
new Saver().start();// Save a little
}
// Saver *******************************************************************
class Saver extends Thread {
Float Amount;
// Constructor
Saver()
{
super();
this.Amount = 0f;
}
public void run()
{
deposit(100f);
deposit(200f);
deposit(300f);
deposit(400f);
}
void deposit(Float Amount)
{
synchronized (Balance) {
Balance += Amount;
}
System.out.println("deposit is:" + Amount);
System.out.println("deposit balance is:" + Balance + " ** " + Thread.currentThread().getName());
if (Balance > 900) {
synchronized (Balance) {
Balance.notifyAll();
insufficient_funds = false;
System.out.println("deposit notifying..." + insufficient_funds);
}
}
}
} // Saver
// Spender *******************************************************************
class Spender extends Thread {
Float Amount;
// Constructor
Spender()
{
super();
this.Amount = 0f;
}
public void run()
{
withdrawal(50f);
withdrawal(100f);
withdrawal(150f);
withdrawal(200f);
}
void withdrawal (Float Amount)
{
System.out.println("withdrawal is:" + Amount);
synchronized (Balance) {
Balance -= Amount;
System.out.println("withdrawal balance is:" + Balance + " ** " + Thread.currentThread().getName());
if (Balance < 0) insufficient_funds = true;
}
// Insufficient Funds.....
synchronized (Balance) {
while (insufficient_funds)
{
System.out.println("Insufficient Funds...." + Balance);
try {
System.out.println("Thread Waiting....." + insufficient_funds);
Balance.wait(); // Relinquish the lock...
// Let the Saver Thread notify when the balance is greater than zero
System.out.println("After Waiting");
}
catch (InterruptedException e)
{
System.out.println("Withdrawal permitted to continue (INTERRUPTED)");
}
insufficient_funds = false;
}
}
}
}
public static void main(String args[])
{
SpendSave spendnsave = new SpendSave();
// Slow up the main thread so we can see how many threads are active...
try {
Thread.sleep(5000);
}
catch (InterruptedException e) {}
System.out.println("Alive Threads:" + Thread.activeCount());
}
}
# 3
Nevermind I figured it out. I will post the solution tomorrow.
# 4
hummmFloat is an immutable object, so i guess when you do "+=" you create a new instance.So you loose the object you were waiting on...
ibanna at 2007-7-12 20:16:34 >

# 5
> hummm
> Float is an immutable object, so i guess when you do
> "+=" you create a new instance.
> So you loose the object you were waiting on...
Of course, with boxing. What you are doing is...
Balance = Float.valueOf( Balance.floatValue() + Amount );
It's usually good practice to make your lock objects final - that way, you can have the compiler tell you about problems!
# 6
Here's the solution. Let me know if there are still any problems with this code
* SpendSave.java: A variation on the consumer /
*producer problem to illustrate
*fine grained synchronization
*of threads.
public class SpendSave {
AccountBalance Balance; // Account Balance
// Constructor *******************************
public SpendSave()
{
Balance = new AccountBalance(0f);
new Spender("Spender").start(); // Spend a little
new Saver("Saver").start();// Save a little
}
// Saver *************************************
class Saver extends Thread {
Float Amount;
// Constructor
Saver(String name)
{
super(name);
this.Amount = 0f;
}
public void run()
{
deposit(100f);
deposit(200f);
deposit(300f);
deposit(400f);
}
void deposit(Float Amount)
{
System.out.println("deposit is: "
+ Amount
+ "\n");
synchronized (Balance) { // acquire lock
Balance.add(Amount);
System.out.println("deposit balance is: "
+ Balance.getBalance()
+ " ** "
+ Thread.currentThread().getName()
+ "\n");
}// lock released
synchronized (Balance) { // reacquire lock
if (!Balance.insufficient_funds()) {
Balance.notifyAll();
System.out.println("Saver thread notifying "
+ "Spender Thread..."
+ "\n");
} // lock released again
}
}
} // Saver
// Spender ***********************************
class Spender extends Thread {
Float Amount;
// Constructor
Spender(String name)
{
super(name);
this.Amount = 0f;
}
public void run()
{
withdrawal(50f);
withdrawal(100f);
withdrawal(150f);
withdrawal(200f);
}
void withdrawal (Float Amount)
{
System.out.println("withdrawal is:"
+ Amount
+ "\n");
synchronized (Balance) { // acquire lock
Balance.sub(Amount);
System.out.println("withdrawal balance is:"
+ Balance.getBalance()
+ " ** "
+ Thread.currentThread().getName()
+ "\n");
} // lock released
// Insufficient Funds.....
synchronized (Balance) { // reacquire lock
while (Balance.insufficient_funds())
{
System.out.println("Insufficient Funds: "
+ Balance.getBalance()
+ "\n");
try {
System.out.println("Spender Thread Waiting..\n");
Balance.wait(); // Relinquish the lock...
// Let the Saver Thread
// notify Spender when
// the balance is greater than zero
System.out.println("Spender Thread Released..\n");
}
catch (InterruptedException e)
{
System.out.println("Withdrawal permitted"
+ "to continue in case interrupt");
}
//insufficient_funds = false;
}
} // lock released again
}
}
public static void main(String args[])
{
SpendSave spendnsave = new SpendSave();
// Slow up the main thread so
// we can see how many threads are currently active...
try {
Thread.sleep(5000);
}
catch (InterruptedException e) {}
System.out.println("Alive Threads:" + Thread.activeCount());
}
}
/*
* AccountBalance.java: Definition of locked object
*/
public class AccountBalance extends Object {
Float balance;
public AccountBalance( Float amount)
{
this.balance = amount;
}
public Float add(Float amount)
{
this.balance += amount;
return this.balance;
}
public Float sub(Float amount)
{
this.balance -= amount;
return this.balance;
}
public Float getBalance()
{
return this.balance;
}
public boolean insufficient_funds() {
if (this.balance < 0f) return true;
else return false;
}
}
Message was edited by:
skalvi
# 7
Don't use Float. You should be using a double or (if you want to use objects) BigDecimal.You are swallowing InterruptedExceptions inside a while loop making it impossible to interrupt the waiting process.
# 8
public boolean insufficient_funds() {
if (this.balance < 0f) return true;
else return false;
}
}
Can be simplified to (using standard Java naming conventions)
public boolean insufficientFunds() {
return this.balance < 0f;
}