/* * Copyright (c) 2010-2012 Grid Dynamics Consulting Services, Inc, All Rights Reserved * http://www.griddynamics.com * * This library is free software; you can redistribute it and/or modify it under the terms of * the Apache License; either * version 2.0 of the License, or any later version. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.griddynamics.jagger.util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Required; import com.google.common.base.Throwables; import com.google.common.util.concurrent.ThreadFactoryBuilder; import java.util.Collection; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class ConfigurableExecutor implements ExecutorService { private static final Logger log = LoggerFactory.getLogger(ConfigurableExecutor.class); private final Object lock = new Object(); private int corePoolSize; private int maximumPoolSize; private ThreadPoolExecutor delegate; private String nameFormat; private ThreadPoolExecutor delegate() { if (delegate == null) { synchronized (lock) { if (delegate == null) { ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat(nameFormat).setUncaughtExceptionHandler(ExceptionLogger.INSTANCE).build(); delegate = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, 180, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), threadFactory); } } } return delegate; } @Required public void setNameFormat(String nameFormat) { this.nameFormat = nameFormat; } @Required public void setCorePoolSize(int corePoolSize) { this.corePoolSize = corePoolSize; log.info("corePoolSize={}", corePoolSize); } @Required public void setMaximumPoolSize(int maximumPoolSize) { this.maximumPoolSize = maximumPoolSize; log.info("maximumPoolSize={}", maximumPoolSize); } @Override public void shutdown() { delegate().shutdown(); } @Override public List<Runnable> shutdownNow() { return delegate().shutdownNow(); } @Override public boolean isShutdown() { return delegate().isShutdown(); } @Override public boolean isTerminated() { return delegate().isTerminated(); } @Override public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { return delegate().awaitTermination(timeout, unit); } @Override public <T> Future<T> submit(Callable<T> task) { return delegate().submit(task); } @Override public <T> Future<T> submit(Runnable task, T result) { return delegate().submit(task, result); } @Override public Future<?> submit(Runnable task) { return delegate().submit(task); } @Override public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException { return delegate().invokeAll(tasks); } @Override public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException { return delegate().invokeAll(tasks, timeout, unit); } @Override public <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException { return delegate().invokeAny(tasks); } @Override public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { return delegate().invokeAny(tasks, timeout, unit); } @Override public void execute(Runnable command) { try { delegate().execute(command); } catch (RejectedExecutionException e) { log.warn("Command {} rejected. Pool size: core {} max {}. Active threads {}" + "\n Exception {}", new Object[]{command, corePoolSize, maximumPoolSize, delegate().getActiveCount(), Throwables.getStackTraceAsString(e)}); } } }