I am trying to code a problem in Java where I have to execute a bunch of tasks.
Problem
Execute a job which consists of multiple tasks and thos
Your question is interesting because someone can simulate a simple neural network using this design. As far as the answer goes, I would like to view the problem as tasks ordering rather than a multithreading/concurrency problem because concurrency can be achieved simply by executing ordered tasks. Now lets try to use event driven programming to achieve that because it allows nice loosely coupled components. So, now our design in reactive in nature, so we will worry about signaling the dependent tasks once we are done, lets use observer pattern here .
Your tasks are both observable and observer as well because they wait on notification from predecessor and notify successor, which gives us the following construct.
// Task.java
public abstract class Task extends Observable implements Runnable, Observer {
private final Mutex lock = new Mutex();
private final String taskId;
public String getTaskId() {
return this.taskId;
}
private final Set completedTasks;
private final Set shouldCompletedTasksBeforeStart;
public Task(final String taskId) {
this.taskId = taskId;
this.completedTasks = new HashSet<>();
this.shouldCompletedTasksBeforeStart = new HashSet<>();
}
@Override
public void run() {
while (true) {
this.lock.getLock();
if (this.completedTasks.equals(this.shouldCompletedTasksBeforeStart)) {
doWork();
setChanged();
notifyObservers(this.taskId);
// reset
this.completedTasks.clear();
}
this.lock.freeLock();
try {
// just some sleep, you change to how it fits you
Thread.sleep(1000);
} catch (final InterruptedException e) {
// TODO Auto-generated catch block
}
}
}
@Override
public void update(final Observable observable, final Object arg) {
this.lock.getLock();
this.completedTasks.add((String) arg);
this.lock.freeLock();
}
public void addPredecessorTask(final Task task) {
if (this.taskId.equals(task.taskId)) {
return;
}
this.lock.getLock();
// Notice here, it is a little logic make your predecessor/successor work
task.addObserver(this);
this.shouldCompletedTasksBeforeStart.add(task.taskId);
this.lock.freeLock();
}
protected abstract void doWork();
}
//HelloTask.java
public static class HelloTask extends Task {
public HelloTask(final String taskId) {
super(taskId);
}
@Override
protected void doWork() {
System.out.println("Hello from " + getTaskId() + "!");
}
}
//Main.java
public class Main {
public static void main(final String[] args) {
final HelloTask helloTaskA = new HelloTask("A");
final HelloTask helloTaskB = new HelloTask("B");
final HelloTask helloTaskC = new HelloTask("C");
helloTaskA.addPredecessorTask(helloTaskB);
helloTaskC.addPredecessorTask(helloTaskB);
final ExecutorService pool = Executors.newFixedThreadPool(10);
pool.execute(helloTaskC);
pool.execute(helloTaskA);
pool.execute(helloTaskB);
}
}
The implementation is very basic one and you improve upon it but it provides you the foundation structure. It would be interesting to know where you are applying this ?