/** * 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(); } } }