protected void configureBuilder(final DependencyGraphBuilder builder) { builder.setMaxAdditionalThreads(getMaxAdditionalThreadsPerBuilder()); }
/** * Constructs {@link DependencyGraphBuider} instances with common parameters. All dependency graph * builders created by a single factory will share the same additional thread allowance. */ public class DependencyGraphBuilderFactory { private static final Logger s_logger = LoggerFactory.getLogger(DependencyGraphBuilderFactory.class); private static final Executor s_executor = Executors.newCachedThreadPool( new ThreadFactory() { private final AtomicInteger _nextJobThreadId = new AtomicInteger(); @Override public Thread newThread(final Runnable r) { final Thread t = new Thread(r) { @Override public void run() { s_logger.info("Starting background thread {}", this); super.run(); s_logger.info("Finished background thread {}", this); } }; t.setDaemon(true); t.setName( DependencyGraphBuilder.class.getSimpleName() + "-" + _nextJobThreadId.incrementAndGet()); return t; } }); private int _maxAdditionalThreadsPerBuilder = DependencyGraphBuilder.getDefaultMaxAdditionalThreads(); private int _maxAdditionalThreads = DependencyGraphBuilder.getDefaultMaxAdditionalThreads(); private final Executor _executor = createExecutor(); public DependencyGraphBuilderFactory() {} public void setMaxAdditionalThreadsPerBuilder(final int maxAdditionalThreadsPerBuilder) { _maxAdditionalThreadsPerBuilder = maxAdditionalThreadsPerBuilder; } public int getMaxAdditionalThreadsPerBuilder() { return _maxAdditionalThreadsPerBuilder; } public void setMaxAdditionalThreads(final int maxAdditionalThreads) { _maxAdditionalThreads = maxAdditionalThreads; } public int getMaxAdditionalThreads() { return _maxAdditionalThreads; } public DependencyGraphBuilder newInstance() { final DependencyGraphBuilder builder = new DependencyGraphBuilder(getExecutor()); configureBuilder(builder); return builder; } protected void configureBuilder(final DependencyGraphBuilder builder) { builder.setMaxAdditionalThreads(getMaxAdditionalThreadsPerBuilder()); } protected Executor createExecutor() { // Wrap calls to the underlying executor so that all threads are pooled but a pool is not // created for each factory return new Executor() { private final AtomicInteger _threads = new AtomicInteger(); private final Queue<Runnable> _commands = new ConcurrentLinkedQueue<Runnable>(); private Runnable wrap(final Runnable command) { return new Runnable() { @Override public void run() { try { s_logger.debug("Starting job execution"); command.run(); } finally { s_logger.debug("Job execution complete"); threadExit(); s_logger.debug("Thread exit complete"); } } }; } private void executeImpl(final Runnable command) { getDefaultExecutor().execute(wrap(command)); } private void threadExit() { int threads = _threads.decrementAndGet(); while (threads < getMaxAdditionalThreads()) { final Runnable command = _commands.poll(); if (command == null) { if (s_logger.isDebugEnabled()) { s_logger.debug("No pending commands to run - {}", threads); } return; } if (s_logger.isDebugEnabled()) { s_logger.debug("Thread capacity available - {}", threads); } threads = _threads.incrementAndGet(); if (threads <= getMaxAdditionalThreads()) { if (s_logger.isDebugEnabled()) { s_logger.debug("Thread capacity {} acquired for execution", threads); } executeImpl(command); return; } if (s_logger.isDebugEnabled()) { s_logger.debug("Too many threads {} - requeuing job", threads); } _commands.add(command); threads = _threads.decrementAndGet(); } } @Override public void execute(final Runnable command) { final int threads = _threads.incrementAndGet(); if (threads <= getMaxAdditionalThreads()) { if (s_logger.isDebugEnabled()) { s_logger.debug("Direct execution - {} threads", threads); } executeImpl(command); return; } // Already started too many jobs if (s_logger.isDebugEnabled()) { s_logger.debug("Too many threads {} - queuing job", threads); } _commands.add(command); threadExit(); } }; } protected static Executor getDefaultExecutor() { return s_executor; } protected Executor getExecutor() { return _executor; } }