0

As I am new to Java Threads, I was just experimenting with my code. From Kathy' Sierra SCJP book, I learnt about thread.join() method. Then I learnt 'bout Synchronization. Below is the code in which I used thread.join() method instead of making makeWithdrawal() method a synchronized.

AccountDanger class:

public class AccountDanger implements Runnable{
    private Account acct=new Account();
    public static void main(String args[])throws InterruptedException{
        AccountDanger r=new AccountDanger();
        Thread one=new Thread(r);
        Thread two=new Thread(r);// unable to start
        one.setName("Fred");
        two.setName("Lucy");
        one.start();
        one.join();// used join() instead of using synchronize keyword.
        two.start();// unable to start
    }
    public void run(){

        for(int x=0;x<5;x++){
            makeWithdrawal(10);
            if(acct.getBalance()<0){
                System.out.println("Account is over-drawn");
            }
        }
    }
    private void makeWithdrawal(int amt){
        if(acct.getBalance()>=amt){
            System.out.println(Thread.currentThread().getName()+" is goint to withdraw");
            try{
                Thread.sleep(500);
            }
            catch(InterruptedException ex){}
            acct.withdraw(amt);
            System.out.println(Thread.currentThread().getName()+" completes the withdrawal");
        }
        else{
            System.out.println("Not enough in account for "+Thread.currentThread().getName()+" to withdraw "+acct.getBalance());
        }
    }
}

Account class:

class Account{
    private int balance=50;
    public int getBalance(){
        return balance;
    }
    public void withdraw(int amount){
        balance=balance-amount;
    }
}

But after seeing the output (more than 10 times), I realized that I was unable to start my second thread (thread with the name Lucy). Actually, after testing with two.isAlive() print statement, I found it to be alive. But why can't i see this Lucy thread working? Why is that? can any one help me? Below is the output I get always get:

Fred is goint to withdraw
Fred completes the withdrawal
Fred is goint to withdraw
Fred completes the withdrawal
Fred is goint to withdraw
Fred completes the withdrawal
Fred is goint to withdraw
Fred completes the withdrawal
Fred is goint to withdraw
Fred completes the withdrawal
Not enough in account for Lucy to withdraw 0
Not enough in account for Lucy to withdraw 0
Not enough in account for Lucy to withdraw 0
Not enough in account for Lucy to withdraw 0
Not enough in account for Lucy to withdraw 0
JPG
  • 1,247
  • 5
  • 31
  • 64
  • Fred is goint to withdraw Fred completes the withdrawal Fred is goint to withdraw Fred completes the withdrawal Fred is goint to withdraw Fred completes the withdrawal Fred is goint to withdraw Fred completes the withdrawal Fred is goint to withdraw Fred completes the withdrawal Not enough in account for Lucy to withdraw 0 Not enough in account for Lucy to withdraw 0 Not enough in account for Lucy to withdraw 0 Not enough in account for Lucy to withdraw 0 Not enough in account for Lucy to withdraw 0 – JPG May 23 '14 at 20:58
  • Don't put logs in comments. Edit your question instead. – Sotirios Delimanolis May 23 '14 at 20:59
  • So you learned about `join()`. What does `join()` do? (You can delete your comments.) – Sotirios Delimanolis May 23 '14 at 21:05
  • It joins the another thread onto the end. In this case, I think second thread(Lucy) should be joined after thread(fred). Please correct me if I am incorrect. – JPG May 23 '14 at 21:12
  • Java has a documentation feature called Javadoc. Look up the javadoc of the `Thread` class and read what `join()` does. – Sotirios Delimanolis May 23 '14 at 21:13
  • Yaa, it says -- "Waits for this thread to die." So, why not 2nd Thread runs after 1st thread is over or died. – JPG May 23 '14 at 21:17
  • It does. Look at your logs. – Sotirios Delimanolis May 23 '14 at 21:19
  • Oh Yeah!, But can you please tell me, why can't I see `Lucy is going to withdraw`. I can't see this statement until now. Why is it so? – JPG May 23 '14 at 21:23
  • Look at your code. Obviously `acct.getBalance()>=amt` is false at that moment. – Sotirios Delimanolis May 23 '14 at 21:24
  • Oh WoW..Now, I figured out. Thank You very much for clearing my doubts. – JPG May 23 '14 at 21:30

1 Answers1

0

No everything is right, but:

you wait for the termination of Thread1 (join wait, until it is finished).

Thread2 will be started, but it is a daemon Thread. There Threads will be terminiated, if the main-Thread is terminated.

Change your code to:

thread1.start();
thread2.start();
thread1.join();
thread2.join();

Now both Threads will be finished (and work parallel).

edit:

Clarification:

one.start(); // Starts the execution of the runnable in Thread "one"
one.join();  // Waits for the Runnable to FINISH
two.start(); // after Thread "one" died, Thread "two" starts (no more moneys in the account)

join(): Waits for this thread to die.

This is the same as calling everything synchron.

Christian Kuetbach
  • 15,850
  • 5
  • 43
  • 79
  • Which one? (I would use ExecutorsService, but this was a question about Thread2 is not starting. (Did not look, into the withdraw, if it is Threadsafe or not) – Christian Kuetbach May 23 '14 at 21:00
  • Right, it's not threadsafe. I'm guessing that is why they wanted to use `join()`, misguidedly. – Sotirios Delimanolis May 23 '14 at 21:02
  • Only because of the explained behavior. "The second thread is not started". I think it may be startet and terminated immidiatly, or not startet, because the main Thread finished and the JVM shuts down.. – Christian Kuetbach May 23 '14 at 21:26
  • You have to explicitly set the thread as a daemon for it to be a daemon thread (or if it's creator is a daemon thread). Nothing in the code post indicates that. I've asked for clarifications. You can see the program output. – Sotirios Delimanolis May 23 '14 at 21:28