/** * Get more info at : www.jrebirth.org . * Copyright JRebirth.org © 2011-2013 * Contact : sebastien.bordes@jrebirth.org * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jrebirth.af.core.concurrent; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.jrebirth.af.api.concurrent.IJRebirthThreadPoolExecutor; import org.jrebirth.af.api.concurrent.JRebirthRunnable; import org.jrebirth.af.api.concurrent.RunnablePriority; import org.jrebirth.af.api.log.JRLogger; import org.jrebirth.af.core.log.JRLoggerFactory; /** * * The class <strong>JRebirthThreadPoolExecutor</strong> is used to to manage the JRebirth Thread Pool (<b>JTP</b>). * * @author Sébastien Bordes */ public class JRebirthThreadPoolExecutor extends ThreadPoolExecutor implements IJRebirthThreadPoolExecutor, ConcurrentMessages { /** The class logger. */ private static final JRLogger LOGGER = JRLoggerFactory.getLogger(JRebirthThreadPoolExecutor.class); /** The pending list of JRebirthRunnable. */ private final List<JRebirthRunnable> pending = new ArrayList<>(); /** * Default Constructor. * * @param threadNumber the number of thread managed by the pool * @param threadFactory the factory used to add a thread into the pool */ public JRebirthThreadPoolExecutor(final int threadNumber, final ThreadFactory threadFactory) { super(threadNumber, threadNumber, 0L, TimeUnit.MILLISECONDS, new PriorityBlockingQueue<Runnable>(threadNumber, new JRebirthRunnableComparator()), threadFactory); } /** * Check if a slot is available for the given task priority. * * @param taskPriority the priority to check * * @return true if this priority can be run right now */ @Override public boolean checkAvailability(final RunnablePriority taskPriority) { // The next task could be added if: // _ a slot is available // _ the task has a lower priority than current executed return getActiveCount() < getCorePoolSize() || checkPriority(taskPriority); } /** * Check given priority with current pending list. * * @param taskPriority the priority to check * * @return true if the priority is greater than those pending */ private boolean checkPriority(final RunnablePriority taskPriority) { boolean highPriority = false; for (final JRebirthRunnable jr : this.pending) { highPriority |= taskPriority.getLevel() > jr.getPriority().getLevel(); } return !highPriority; } // /** // * Execute the JRebirthRunnable. // * // * @param task to run // */ // public void execute(final JRebirthRunnable task) { // super.execute(task); // } /** * {@inheritDoc} */ @Override protected void beforeExecute(final Thread t, final Runnable r) { this.pending.add((JRebirthRunnable) r); super.beforeExecute(t, r); } /** * {@inheritDoc} */ @Override protected void afterExecute(final Runnable r, final Throwable t) { super.afterExecute(r, t); this.pending.remove(r); Throwable rootCause = null; if (t == null && r instanceof Future<?>) { try { final Object result = ((Future<?>) r).get(); if (result != null) { LOGGER.log(FUTURE_DONE, r.hashCode(), result.toString()); } } catch (final CancellationException | ExecutionException e) { rootCause = e.getCause(); } catch (final InterruptedException ie) { Thread.currentThread().interrupt(); // ignore/reset } } if (t != null) { LOGGER.log(JTP_ERROR, t); } if (rootCause != null) { LOGGER.log(JTP_ERROR_EXPLANATION, rootCause); } } }