/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.processor;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import net.sourceforge.pmd.PMDConfiguration;
import net.sourceforge.pmd.Report;
import net.sourceforge.pmd.renderers.Renderer;
/**
* @author Romain Pelisse <belaran@gmail.com>
*
*/
public class MultiThreadProcessor extends AbstractPMDProcessor {
private ThreadFactory factory;
private ExecutorService executor;
private CompletionService<Report> completionService;
private List<Future<Report>> tasks = new ArrayList<>();
public MultiThreadProcessor(final PMDConfiguration configuration) {
super(configuration);
factory = new PmdThreadFactory();
executor = Executors.newFixedThreadPool(configuration.getThreads(), factory);
completionService = new ExecutorCompletionService<>(executor);
}
@Override
protected void runAnalysis(PmdRunnable runnable) {
// multi-threaded execution, dispatch analysis to worker threads
tasks.add(completionService.submit(runnable));
}
@Override
protected void collectReports(List<Renderer> renderers) {
// Collect result analysis, waiting for termination if needed
try {
for (int i = 0; i < tasks.size(); i++) {
final Report report = completionService.take().get();
super.renderReports(renderers, report);
}
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
} catch (ExecutionException ee) {
Throwable t = ee.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else if (t instanceof Error) {
throw (Error) t;
} else {
throw new IllegalStateException("PmdRunnable exception", t);
}
} finally {
executor.shutdownNow();
}
}
}