TLDR:
Use just one constructor that accepts a Runnable and a member of type Runnable.
Long answer:
If you really, really need to have two difrerent constructors, one that receives a TaskA and one that receives a TaskB, (one possible reason is that TaskManager calls methods that are particular to TaskA or TaskB) then you have two options:
- Have two members,
private TaskA taskA and private TaskB taskB - Have just one member
private Runnable task, since Runnable is the common ancestor of TaskA and TaskB
In the other hand, if you don't really need a constructor for each type of task, you can have just one constructor public TaskManager(Runnable task) and only one member of type Runnable like in option 2 previously stated.
It all dependends of whether or not you will need to call methods that are particular to TaskA or TaskB. If TaskManager only really cares about the Runnable contract then there's no need for two constructors, let alone having to cast an Object to a Runnable to run it.
Lastly, if TaskManager really needs something from the tasks beside the Runnable functionality, then create a RunnableTask like this:
public interface RunnableTask extends Runnable { public int getThis(); public int getThat(); } public class TaskA implements RunnableTask { ... } public class TaskB implements RunnableTask { ... } public class TaskManager { ... private RunnableTask task; public TaskManager(RunnableTask task) { this.task = task; } public void startThreadPool() { threadPool = new ThreadPoolExecutor(...); threadPool.execute(task); // do somewthing with task.getThis(); // do somewthing with task.getThat(); } ... }
private Runnable task;... and I'm not sure what yourTaskManageroffers above and beyond what theThreadPoolExecutoroffers anyway.