views:

112

answers:

3

What are the correct ways/practice/implementation/strategies (or whatever we call it as) for not to wait for code block/method to finish execution in Java?

Assume the following method:

private void myMethod()
{
     // Some lines of code here
     .....
     .....
     .....

     anotherMethod(); // or this could be a code block

     // Again some lines of code here
     .....
     .....
     .....
}

In this case, I expect myMethod() should not wait for code to finish execution of anotherMethod(). I can also assure here that subsequent lines of code do not depend on anything getting executed within anotherMethod().

+6  A: 

You can start it in another Thread if there is no dependency .

new Thread(new Runnable(){

      public void run(){
           anotherMethod();
      }  

}).start();
org.life.java
@org.life.java: Just a small correction in your code block - it is `new Thread(...){...`.
Gnanam
@org.life.java: What is the difference in implementation between yours and the one suggested by `Bozho`?
Gnanam
@Gnanam `Bozho's suggestion Executes the given command at some time in the future. The command may execute in a new thread, in a pooled thread, or in the calling thread, at the discretion of the Executor implementation.`
org.life.java
@org, but in this case each executor uses a single thread, and he's creating a new executor every time. So as far as I can tell, it's basically the same thing with more overhead and improper cleanup.
Matthew Flaschen
@org.life.java: Though I've not mentioned this in my original question, actually am passing parameters to this `anotherMethod();`. So on compiling, am getting `local variable myParams is accessed from within inner class; needs to be declared final`. Here `myParams` object is the parameter passed to `anotherMethod();`. How do I solve in this case?
Gnanam
@Gnanam make myParams final, or if you can't make myParams final because it is reassigned elsewhere, create a new final local variable newMyParams and assign myParams to it, then pass newMyParams to anotherMethod();
ILMTitan
@Gnanam exactly same as @ILMTitan suggested.
org.life.java
@ILMTitan: Thanks for your comments.
Gnanam
A: 

If you want to invoke the method in the same thread, then the method itself must provide an asynchronous (i.e. non-blocking) implementation. Usually this will involve returning some sort of callback such as a Future, which you can poll/query later to fetch the actual result. An example of this is the ExecutorService.submit() calls - the code you supply will be run, but in a background thread leaving you free to call other methods in the meantime.

I bolded the word invoke before, since fundamentally the only way in Java to have two things happening at once is to use multiple threads. So the method/code block/whatever will have to be executing in a background thread one way or another - usually this is handled for you in an asynchronous method by using some sort of thread pool or whatever is appropriate.

If the method doesn't provide an asynchronous interface, however, the only way to get its logic to run in another thread is to spawn that thread yourself, as org.life.java suggests.

Andrzej Doyle
+7  A: 

Use

Executor executor = Executors.newSingleThreadExecutor();
executor.execute(new Runnable() {
    @Override
    public void run() {
       anotherMethod();
    }
});
// this is called automatically when the object is gc-ed, 
// but you should not rely on this, hence the explicit call
executor.shutdown();

To quote Effective Java:

Not only should you refrain from writing your own work queues, but you should generally refrain from working directly with threads. The key abstraction is no longer Thread, which served as both the unit of work and the mechanism for executing it. Now the unit of work and mechanism are separate. The key abstraction is the unit of work, which is called a task. There are two kinds of tasks: Runnable and its close cousin, Callable (which is like Runnable, except that it returns a value). The general mechanism for executing tasks is the executor ser- vice. If you think in terms of tasks and let an executor service execute them for you, you gain great flexibility in terms of selecting appropriate execution policies. In essence, the Executor Framework does for execution what the Collections Framework did for aggregation.

Note that you'd better create your executor only once, store it in an instance field and reuse it (and shut it down afterwards)

If you are running in JavaEE 6 or spring, you can annotate your anotherMethod() with @Asynchronous and the container will start a new thread for you.

Bozho
Don't forget to `shutdown()` the ExecutorService when you are done with it
dogbane
@Bozho: What is the difference in implementation between yours and the one suggested by `org.life.java`.
Gnanam
@Gnanam - mine is more Java 5+ :) his suggestion was used before, and is more low-level.
Bozho
@Gnanam: he uses a thread pool -- newSingleThreadExecutor creates a threadpool that uses a single worker thread operating off an unbounded queue. Remember always shutdown a threadpool after usage.
SiLent SoNG
@Bozho, isn't `newSingleThreadExecutor` intended for using multiple times? I.E. you have one SingleThreadExecutor (which uses one thread), but it can queue up and execute multiple jobs in sequence. I don't see a benefit here. Also, @SiLent is right, you can't shutdown the service properly, since you're not keeping a reference.
Matthew Flaschen
Code is not clear and misleading -- thread pool is expensive and should not be used just once here at method level. You also forget to dispose the thread pool.
SiLent SoNG
well, what's wrong with using an executor for just one execution?
Bozho
@Bozho, it adds overhead for no apparent reason. As I said, that executor is intended to be used for multiple jobs.
Matthew Flaschen
and what is the overhead? Construction of the service object?
Bozho
Yes. It's not a big overhead, but it's overhead with no apparent benefit.
Matthew Flaschen
Effective Java has taught me to avoid working with threads directly, hence my answer.
Bozho
@Bozho, your modified answer makes more sense. You should clarify that you would generally store `executor` in a field, and use it multiple times. To quote EJ, you couldn't really "select[] appropriate execution policies" when you're creating a executor inline then discarding it. With a field, you have much more flexibility to use dependency injection or similar to choose an executor.
Matthew Flaschen
@Matthew Flaschen true. I'll add a note about that.
Bozho