8

I want to know the best way how to notify another thread. For example, I have a background thread:

public void StartBackgroundThread(){
new Thread(new Runnable() {         
        @Override
        public void run() {
            //Do something big...
            //THEN HOW TO NOTIFY MAIN THREAD?
        }
    }).start();
}

When it finished it has to notify main thread? If somebody knows the best way how to do this I'll appreciate it!

Nolesh
  • 6,848
  • 12
  • 75
  • 112
  • Consider reading the following: http://www.javaworld.com/javaworld/jw-07-2002/jw-0703-java101.html It covers notification. (Specifically page 7) – BlackVegetable Jan 15 '13 at 01:20
  • What will the main thread be doing while the second thread does "something big"? Will it only be waiting on the second thread? If so, why do you need a second thread at all? If not, you need to say a bit more about what it will be doing. – Bruno Reis Jan 15 '13 at 02:03
  • The main thread will be rendering the GUI, for example... – Nolesh Jan 15 '13 at 04:03

5 Answers5

4

The typical answer is a BlockingQueue. Both BackgroundThread (often called the Producer) and MainThread (often called the Consumer) share a single instance of the queue (perhaps they get it when they are instantiated). BackgroundThread calls queue.put(message) each time it has a new message and MainThread calls 'queue.take()which will block until there's a message to receive. You can get fancy with timeouts and peeking but typically people want aBlockingQueueinstance such asArrayBlockingQueue`.

dough
  • 714
  • 5
  • 14
4

Purely based on your question you could do this:

public class test
{
  Object syncObj = new Object();

  public static void main(String args[])
  {
    new test();
  }

  public test()
  {
    startBackgroundThread();

    System.out.println("Main thread waiting...");
    try
    {
      synchronized(syncObj)
      {
        syncObj.wait();
      }
    }
    catch(InterruptedException ie) { }
    System.out.println("Main thread exiting...");
  }

  public void startBackgroundThread()
  {
    (new Thread(new Runnable()
    {
      @Override
      public void run()
      {
        //Do something big...
        System.out.println("Background Thread doing something big...");
        //THEN HOW TO NOTIFY MAIN THREAD?
        synchronized(syncObj)
        {
          System.out.println("Background Thread notifing...");
      syncObj.notify();
        }
        System.out.println("Background Thread exiting...");
      }
    })).start();
  }
}

and see this output

PS C:\Users\java> javac test.java
PS C:\Users\java> java test
Main thread waiting...
Background Thread doing something big...
Background Thread notifing...
Background Thread exiting...
Main thread exiting...
jco.owens
  • 535
  • 2
  • 5
2

You can't "notify the main thread".

The best approach is to use an ExecutorService, like this for example:

 import java.util.concurrent.*;

 // in main thread
 ExecutorService executorService = Executors.newSingleThreadExecutor();

 Future<?> future = executorService.submit(new Runnable() {         
    @Override
    public void run() {
        //Do something big...
    }
});

future.get(); // blocks until the Runnable finishes

The classes are written specially to deal with asynchronous operations, and all the code in there is already written for you and bullet-proof.

Edit

If you don't want to block the main thread while waiting, wait within another thread:

 final Future<?> future = executorService.submit(new Runnable() {         
    @Override
    public void run() {
        //Do something big...
    }
});

new Thread(new Runnable() {         
    @Override
    public void run() {
        future.get(); // blocks until the other Runnable finishes
        // Do something after the other runnable completes
    }
}).start();
Community
  • 1
  • 1
Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • can you please let me know why we can't notify the main thread? I'm interested in knowing – vishal_aim Jan 15 '13 at 03:38
  • But what if I want to do something after the other runnable completes in main thread? – Nolesh Jan 15 '13 at 13:19
  • Replace the comment `// Do something after the other runnable completes` in the code in my answer with whatever you need to do – Bohemian Jan 15 '13 at 13:59
1

Just call notify()

public void run() { 
    try { 
        while ( true ) { 
            putMessage(); 
            sleep( 1000 ); 
        } 
    }  
    catch( InterruptedException e ) { } 
} 

private synchronized void putMessage() throws InterruptedException { 
    while ( messages.size() == MAXQUEUE ) 
        wait(); 

    messages.addElement( new java.util.Date().toString() ); 
    notify(); 
} 
SpiffyDeveloper
  • 127
  • 1
  • 7
0

One thread notifying another thread is not a good way to do it. Its better to have 1 master thread that gives the slave thread work. The slave thread is always running and waits until it receives work. I recommend that you draw two columns and determine exactly where each thread needs to wait.

    public void run() 
    {
    //Do something big...
    synchronized(this)
    {
        done = true;
    }
    }

Java includes libraries that make this really easy see ExecutorService and the following post Producer/Consumer threads using a Queue

Community
  • 1
  • 1
Mikhail
  • 7,749
  • 11
  • 62
  • 136