it seems to me that i get poor performance using the following SupervisedExecutor and ExecutorSuperviser implementation of my own, What do you think can be unefficient in this code? I want to learn how can i improve its effciency.
ExecutorSuperviser Class:
public class ExecutorSuperviser {
private SupervisedExecutor[] threadPool;
private int poolSize = 0;
private LinkedList<Runnable> q;\\my own implementation of linkedlist
public ExecutorSuperviser(int nThreads) {
threadPool=new SupervisedExecutor[poolSize=nThreads];
q=new LinkedList<Runnable>();
init();
}
public void execute(Runnable r) {
synchronized (q) {
q.addToTail(r);
}
for (int i=0;i<poolSize;i++)
if (!threadPool[i].isBusy()) {
if (!threadPool[i].isAlive()) threadPool[i].start();
threadPool[i].interrupt();
return;
}
}
private void init() {
for (int i=0;i<poolSize;i++) {
threadPool[i]=new SupervisedExecutor(this);
}
}
public Object getLock() {
return q;
}
public Runnable getTask() {
return q.removeHead();
}
public void terminate() {
for (int i=0;i<poolSize;i++)
threadPool[i].terminate();
}
public void waitUntilFinished() {
while (!isFinished()) {
try {
Thread.sleep(Thread.MAX_PRIORITY);
} catch (InterruptedException e) {}
}
}
private boolean isFinished() {
for (int i=0;i<poolSize;i++)
if (threadPool[i].isBusy()) return false;
return q.isEmpty();
}
}
SupervisedExecutor Class:
public class SupervisedExecutor extends Thread {
private boolean terminated = false;
private Boolean busy = false;
private ExecutorSuperviser boss;
SupervisedExecutor (ExecutorSuperviser boss) {
this.boss=boss;
}
public void run() {
while (!terminated) {
try {
sleep(MAX_PRIORITY);
} catch (InterruptedException e) {
synchronized (busy) {
busy=true;
}
Runnable r;
while (true) {
synchronized (boss.getLock()) {
r=boss.getTask();
}
if (r!=null) r.run();
else break;
}
synchronized (busy) {
busy=false;
}
}
}
}
public boolean isBusy() {
boolean isBusy;
synchronized (boss.getLock()) {
isBusy=busy;
}
return isBusy;
}
public void terminate() {
terminated=true;
}
}
How about the following solution which has the following advantages:
As a subclass of ThreadPoolExecutor, you don’t have to re-implement everything which
ThreadPoolExecutordoes for you just to get thewaitUntilFinished()functionality that you’re after.By taking advantage of
ReentrantLock,Condition, andawait()/signal()you avoid busy waiting, which can certainly hurt performance.This implementation works by taking advantage of the
beforeExecute()andafterExecute()methods whichThreadPoolExecutorexposes to keep our own count of active tasks. I don’t usegetActiveCount()because, according to the JavaDoc, it doesn’t guarantee an exact answer (although perhaps in the case ofThreadPoolExecutorit does provide an exact answer, I’d need to research further to be sure).I included a simple
main()method which you can use as a test case. It starts 10 threads which wait a random amount of time before printing that they are done. Then the main thread callswaitUntilFinished().The results will look something like (the main point being that
Done waiting.will always be printed last: