user986139
user986139

Reputation:

Is it possible to declare a self executing runnable?

Like so?

abstract public class BaseTask extends Runnable {
    public BaseTask(ParamA aParam) {
         // do something with aParam
         StaticExecutorService.submit(this);
    }
}

public class AbcTask extends BaseTask {
    public ABC(ParamA aParam, ParamB bParam) {
        super(aParam);
    }
    @Override
    public void run() {

    }
}

The class can then just be created and queued for execution by doing a

new AbcTask();
  1. I'm not sure if this is ok because maybe it is still being constructed when ExecutorService decides to execute AbcTask?

  2. If you don't recommend this for whatever reason, please state and elaborate.

Thanks

Upvotes: 3

Views: 338

Answers (4)

Kowser
Kowser

Reputation: 8261

  1. Its tightly coupled
  2. In Effective Java, Joshua Bloch explained why it is not a good practice to invoke a protected/public method from a constructor. See 2nd edition, CH-4: Constructors must not invoke overridable methods, directly or indirectly.

    StaticExecutorService.submit(this);
    

    Above line will invoke the public method run from the constructor, and this is not expected.


Explanation from the book: Constructors must not invoke overridable methods, directly or indirectly

If you violate this rule, program failure will result. The superclass constructor runs before the subclass constructor, so the overriding method in the subclass will get invoked before the subclass constructor has run. If the overriding method depends on any initialization performed by the subclass constructor, the method will not behave as expected.

Upvotes: 1

gabuzo
gabuzo

Reputation: 7778

In your example it will probably work but as the call to super() has to be the first in child classes of BaseTask this means that the constructor won't be able to perform any operation before the submission of the task.

From you sample, the second parameter cannot be used since the task will be submitted before you can assign it to an attribute.

If we consider the following code:

public class MyTask extends BaseTask {
    public ABC(ParamA aParam, String name) {
        super(aParam);
        this.name = name == null ? "Default Value" : name;
    }
    @Override
    public void run() {
         System.out.println("Name length: "+ name.length());
    }
}

Since run() can be called before the assignment of this.name the System.out line can end in NullPointerException

Upvotes: 0

Azodious
Azodious

Reputation: 13872

We should not use this until the constructor is completed.

An object is instantiated fully after completion of it's c'tor. so the object passed within StaticExecutorService might not be created fully and may not be usable.

I don't know if specification supports my above statement. but i feel so.

Hence, acc. to me it should be avoided.

Upvotes: 1

Fred Foo
Fred Foo

Reputation: 363597

This might work (at least, I'm not familiar enough with Java to see why it wouldn't), but I would not recommend it as it introduces too strong a coupling: AbcTask would be tied to StaticExecutorService and would be less reusable than it could easily be. This will also make the AbcTask harder to test and debug.

Also, you're "overloading" the meaning of object construction by folding submission to an executor into it. What if, later on, you decide you want to do something to AbcTask objects in between constructing them and submitting them?

Upvotes: 2

Related Questions