| // |
| // ======================================================================== |
| // Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd. |
| // ------------------------------------------------------------------------ |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v1.0 |
| // and Apache License v2.0 which accompanies this distribution. |
| // |
| // The Eclipse Public License is available at |
| // http://www.eclipse.org/legal/epl-v10.html |
| // |
| // The Apache License v2.0 is available at |
| // http://www.opensource.org/licenses/apache2.0.php |
| // |
| // You may elect to redistribute this code under either of these licenses. |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.util.thread; |
| |
| import java.util.concurrent.ArrayBlockingQueue; |
| import java.util.concurrent.BlockingQueue; |
| import java.util.concurrent.ExecutorService; |
| import java.util.concurrent.LinkedBlockingQueue; |
| import java.util.concurrent.RejectedExecutionException; |
| import java.util.concurrent.SynchronousQueue; |
| import java.util.concurrent.ThreadPoolExecutor; |
| import java.util.concurrent.TimeUnit; |
| |
| import org.eclipse.jetty.util.component.AbstractLifeCycle; |
| import org.eclipse.jetty.util.component.LifeCycle; |
| import org.eclipse.jetty.util.log.Log; |
| import org.eclipse.jetty.util.log.Logger; |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Jetty ThreadPool using java 5 ThreadPoolExecutor |
| * This class wraps a {@link ExecutorService} as a {@link ThreadPool} and |
| * {@link LifeCycle} interfaces so that it may be used by the Jetty <code>org.eclipse.jetty.server.Server</code> |
| */ |
| public class ExecutorThreadPool extends AbstractLifeCycle implements ThreadPool, LifeCycle |
| { |
| private static final Logger LOG = Log.getLogger(ExecutorThreadPool.class); |
| private final ExecutorService _executor; |
| |
| /* ------------------------------------------------------------ */ |
| public ExecutorThreadPool(ExecutorService executor) |
| { |
| _executor = executor; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Wraps an {@link ThreadPoolExecutor}. |
| * Max pool size is 256, pool thread timeout after 60 seconds and |
| * an unbounded {@link LinkedBlockingQueue} is used for the job queue; |
| */ |
| public ExecutorThreadPool() |
| { |
| // Using an unbounded queue makes the maxThreads parameter useless |
| // Refer to ThreadPoolExecutor javadocs for details |
| this(new ThreadPoolExecutor(256, 256, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>())); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Wraps an {@link ThreadPoolExecutor}. |
| * Max pool size is 256, pool thread timeout after 60 seconds, and core pool size is 32 when queueSize >= 0. |
| * @param queueSize can be -1 for using an unbounded {@link LinkedBlockingQueue}, 0 for using a |
| * {@link SynchronousQueue}, greater than 0 for using a {@link ArrayBlockingQueue} of the given size. |
| */ |
| public ExecutorThreadPool(int queueSize) |
| { |
| this(queueSize < 0 ? new ThreadPoolExecutor(256, 256, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()) : |
| queueSize == 0 ? new ThreadPoolExecutor(32, 256, 60, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()) : |
| new ThreadPoolExecutor(32, 256, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(queueSize))); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Wraps an {@link ThreadPoolExecutor} using |
| * an unbounded {@link LinkedBlockingQueue} is used for the jobs queue; |
| * @param corePoolSize must be equal to maximumPoolSize |
| * @param maximumPoolSize the maximum number of threads to allow in the pool |
| * @param keepAliveTime the max time a thread can remain idle, in milliseconds |
| */ |
| public ExecutorThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime) |
| { |
| this(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.MILLISECONDS); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Wraps an {@link ThreadPoolExecutor} using |
| * an unbounded {@link LinkedBlockingQueue} is used for the jobs queue. |
| * @param corePoolSize must be equal to maximumPoolSize |
| * @param maximumPoolSize the maximum number of threads to allow in the pool |
| * @param keepAliveTime the max time a thread can remain idle |
| * @param unit the unit for the keepAliveTime |
| */ |
| public ExecutorThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit) |
| { |
| this(corePoolSize, maximumPoolSize, keepAliveTime, unit, new LinkedBlockingQueue<Runnable>()); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| |
| /** |
| * Wraps an {@link ThreadPoolExecutor} |
| * @param corePoolSize the number of threads to keep in the pool, even if they are idle |
| * @param maximumPoolSize the maximum number of threads to allow in the pool |
| * @param keepAliveTime the max time a thread can remain idle |
| * @param unit the unit for the keepAliveTime |
| * @param workQueue the queue to use for holding tasks before they are executed |
| */ |
| public ExecutorThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) |
| { |
| this(new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue)); |
| } |
| |
| |
| /* ------------------------------------------------------------ */ |
| @Override |
| public void execute(Runnable job) |
| { |
| _executor.execute(job); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| public boolean dispatch(Runnable job) |
| { |
| try |
| { |
| _executor.execute(job); |
| return true; |
| } |
| catch(RejectedExecutionException e) |
| { |
| LOG.warn(e); |
| return false; |
| } |
| } |
| |
| /* ------------------------------------------------------------ */ |
| public int getIdleThreads() |
| { |
| if (_executor instanceof ThreadPoolExecutor) |
| { |
| final ThreadPoolExecutor tpe = (ThreadPoolExecutor)_executor; |
| return tpe.getPoolSize() - tpe.getActiveCount(); |
| } |
| return -1; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| public int getThreads() |
| { |
| if (_executor instanceof ThreadPoolExecutor) |
| { |
| final ThreadPoolExecutor tpe = (ThreadPoolExecutor)_executor; |
| return tpe.getPoolSize(); |
| } |
| return -1; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| public boolean isLowOnThreads() |
| { |
| if (_executor instanceof ThreadPoolExecutor) |
| { |
| final ThreadPoolExecutor tpe = (ThreadPoolExecutor)_executor; |
| // getActiveCount() locks the thread pool, so execute it last |
| return tpe.getPoolSize() == tpe.getMaximumPoolSize() && |
| tpe.getQueue().size() >= tpe.getPoolSize() - tpe.getActiveCount(); |
| } |
| return false; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| public void join() throws InterruptedException |
| { |
| _executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| @Override |
| protected void doStop() throws Exception |
| { |
| super.doStop(); |
| _executor.shutdownNow(); |
| } |
| } |