1

I have written a class in Java:

public class Main {
    public static boolean firstRunning = true;
    public static void main(String[] args) {
        (new Thread(){
            public void run(){
                secondFunction();
            }
        }).start();
        firstFunction();
    }

    public static void firstFunction()
    {
        for(int i = 0; i < 10 && firstRunning; i++)
        {
            try{Thread.sleep(1000);} catch(Exception e){}
            System.out.println("first - "+i);
        }
        return;
    }

    public static void secondFunction(){
        try{Thread.sleep(3000);} catch(Exception e){}
        firstRunning = false;
        for(int i = 0; i < 10; i++)
        {
            try{Thread.sleep(700);} catch(Exception e){}
            System.out.println("second - "+i);
        }
    }
}

I am calling the secondFuntion() in a new Thread after which I begin the execution of firstFuntion() in the Main Thread. After the execution of the Thread.sleep(3000) in the secondFuntion(), I want to make secondFunction() take over the Main Thread, for which I set the boolean flag firstRunning to false and cancel the execution of the Main Thread using the return statement.

This approach works for me, but is there a more elegant way of doing the same?

EDIT

The output of the code is

first - 0
first - 1
first - 2
second - 0
second - 1
second - 2
second - 3
second - 4
second - 5
second - 6
second - 7
second - 8
second - 9
Alok Mysore
  • 606
  • 3
  • 16
  • @CocoNess, Could you please show me how or point me to a guide? I'm new to Threaded programming. Thanks :) – Alok Mysore Jul 04 '14 at 10:19
  • 4
    `firstRunning` needs to be `volatile` or the code above might not work as expected. – Aaron Digulla Jul 04 '14 at 10:20
  • I read up what `volatile` is, I'll keep that in mind. Thanks @AaronDigulla. – Alok Mysore Jul 04 '14 at 10:22
  • @AaronDigulla - even with `volatile`, he could still end up with a race condition right?. I mean, the output could still vary. wouldn't it be better to synchronize access to the variable? – TheLostMind Jul 04 '14 at 10:25
  • @TheLostMind: He didn't say he wanted exactly this output (i.e. main must have finished before the second thread is allowed to start). – Aaron Digulla Jul 04 '14 at 10:27
  • @AaronDigulla - I agree.. Still, I don't think he would want an output that keeps varying :P – TheLostMind Jul 04 '14 at 10:28
  • @AaronDigulla, This is the expected result of the code. I was only wondering if there was a more elegant way of doing things. – Alok Mysore Jul 04 '14 at 10:30
  • @TheLostMind, "Race condtion" is not always a bad thing, and it is not always possible to avoid one. There is no point in using a "synchronized" block here because there is only one variable, and it can only have one of two possible values, true or false. There are no invalid/intermediate states that one thread must prevent other threads from seeing. – Solomon Slow Jul 04 '14 at 14:20

3 Answers3

0

If you just want to make the main thread exit, then this is the most simple way to do it.

But usually, you have more complex / different needs. My guess is that you try to solve a different problem and this was your first solution. Unless you tell us about your original problem, we can't tell you what a good solution would be.

If you just want 2 threads to share something (i.e. not use it at the same time), you can use a lock (see Java 7 docs).

Pseudocode:

  • Main thread creates the lock
  • Main thread creates second thread and passes the lock to it
  • First function tries to acquire lock inside of the loop. When it suceeds, it runs the loop body once and releases the lock.
  • Thread 2 then uses the lock to make sure the main thread blocks while it does its work
Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • I don't really have a more complex need. I was tinkering with some code to learn how this works. Thanks :) – Alok Mysore Jul 04 '14 at 10:31
  • 1
    Note that with your approach, the second thread can start to work while the first one is still inside the loop. So you can get the output `...` `second 0` `first 2` `...` – Aaron Digulla Jul 04 '14 at 10:43
0

In my opinion there is no need to actively wait. A more elegant approach is to use a CountDownLatch for this specific problem. If you want the main thread to wait until an other thread did perform an operation, you could for exmple use a CountDownLatch like this:

public class Main {
   private static final CountDownLatch latch = new CountDownLatch(1);
   public static void main(String[] args) throws InterruptedException {
       (new Thread(){
           public void run(){
               secondFunction();
           }
       }).start();
       firstFunction();
       System.out.println("DONE!");
   }

    public static void secondFunction(){
        latch.await(); // blocks the main thread here until 
                       // the latch has been counted down to 0
    }

   public static void secondFunction(){
       System.out.println("secondFunction 1");
       try{Thread.sleep(3000);} catch(Exception e){}
       System.out.println("secondFunction 2");
       latch.countDown(); // this counts down the latch from 1 to 0 and
                          // releases the initial thread from blocking
       // ... continue with some other operations
   }

Output:

secondFunction 1
secondFunction 2
DONE!

Have a look at the Java documentation for more details. An alternative to this approach and the "standard" way of solving thread waiting problems in Java is the so called "monitor" concept using synchronize/wait/notify. Have a look at this stackoverflow post for an example.

Community
  • 1
  • 1
AlexLiesenfeld
  • 2,872
  • 7
  • 36
  • 57
-2

As your real problem is not clear from the question, just to achieve your output you can use the following code. It uses the synchronization, wait/notify functionality given by Threads in java:

public class Main {
    private static Thread t1;
    private static Object lock = new Object();//dummy object to perform sychronization
    public static void main(String[] args) {
        t1 = new Thread(){
            public void run(){
                secondFunction();
            }
        };
        t1.start();
        firstFunction();
    }

    public static void firstFunction()
    {
        for(int i = 0; i < 10; i++)
        {
            if(i == 3){
                 synchronized (lock) { // wait till the lock is available 
                    try {
                        lock.wait(); // wait till some thread notifies
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            try{Thread.sleep(1000);} catch(Exception e){}
            System.out.println("first - "+i);
        }
        return;
    }

    public static void secondFunction(){
        try{Thread.sleep(3000);} catch(Exception e){} //wait for 3 sec to run the main thread 3 times
        synchronized (lock) { //aquire the lock
             for(int i = 0; i < 10; i++)
             {
                 try{Thread.sleep(700);} catch(Exception e){}
                 System.out.println("second - "+i);
             }
               //don't notify the main thread that this thread is done with lock
        }
    }
}

As the code is not notifying that "lock" is no more in use through second function and the new thread, the main thread will keep on waiting for the notification.

Output is same as given in question.

Warning: This is not the good way to use lock and synchronization but just to give you an example of how threads lock/synchronization can be used. Had your real problem been clear, We would have decided the best approach for it

Ishan Rastogi
  • 808
  • 2
  • 8
  • 17