// Implemented as a solution to the question in: http://stackoverflow.com/questions/13005964/thread-pool-where-workers-are-both-producers-and-consumers
public class WorkUnit implements Runnable, Comparable<WorkUnit> {
// the maximum and actual time in ms this job will spend simulating processing
private long maxJobTimeMS, processingTime;
// an integer to specify the maximum number of other work units this one may spawn
private int maxBranchingFactor;
// an executor to schedule new jobs to
private TestExecutor executor;
public WorkUnit(long maxJobTimeMS, int maxBranchingFactor, TestExecutor executor) {
this.maxJobTimeMS = maxJobTimeMS;
this.maxBranchingFactor = maxBranchingFactor;
this.executor = executor;
this.processingTime = randomLong(this.maxJobTimeMS);
}
public void run() {
// simulate some processing time
try {
Thread.sleep(this.processingTime);
System.out.println(this.toString() + " took " + this.processingTime + "ms.");
}
catch(InterruptedException e) {
if(executor.awaitCompletionTimedOut()) {
terminateWork();
}
}
// submit a random number of new jobs up to a maximum branching factor before completion
int newJobCount = (int)randomLong(this.maxBranchingFactor);
while(newJobCount-- > 0 && !executor.awaitCompletionTimedOut()) {
long newWaitTime = randomLong(this.maxJobTimeMS);
System.out.println(this.toString() + " generated a new job which will take: " + newWaitTime + "ms.");
this.executor.executeJob(new WorkUnit(maxJobTimeMS, maxBranchingFactor, executor));
}
}
private void terminateWork() {
System.out.println(this.toString() + " has been interrupted and encountered a timeout; exiting...");
}
private long randomLong(long max) {
return Math.round(Math.random() * (double)max);
}
public int compareTo(WorkUnit o) {
if(this == o) {
return 0;
}
// example job ordering: here, short jobs over longer ones
return Long.compare(this.processingTime, o.processingTime);
}
}