/* * Copyright (C) 2003-2013 eXo Platform SAS. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see<http://www.gnu.org/licenses/>. */ package org.exoplatform.forum.common.lifecycle; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.exoplatform.container.xml.InitParams; import org.exoplatform.forum.common.InitParamsValue; public class LifeCycleCompletionService { private final String THREAD_NUMBER_KEY = "thread-number"; private final String ASYNC_EXECUTION_KEY = "async-execution"; private final String PRIORITY_KEY = "thread-priority"; private final String KEEP_ALIVE_TIME = "keepAliveTime"; private Executor executor; private ExecutorCompletionService<?> ecs; private BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>(); private final int DEFAULT_THREAD_NUMBER = 1; private final boolean DEFAULT_ASYNC_EXECUTION = true; private final int DEFAULT_KEEP_ALIVE_TIME = 10; private final int DEFAULT_THREAD_PRIORITY = 10; private final boolean configAsyncExecution; public LifeCycleCompletionService(InitParams params) { // final int configThreadNumber = InitParamsValue.getInteger(params, THREAD_NUMBER_KEY, DEFAULT_THREAD_NUMBER); final int keepAliveTime = InitParamsValue.getInteger(params, KEEP_ALIVE_TIME, DEFAULT_KEEP_ALIVE_TIME); final int threadPriority = InitParamsValue.getInteger(params, PRIORITY_KEY, DEFAULT_THREAD_PRIORITY); this.configAsyncExecution = InitParamsValue.getBoolean(params, ASYNC_EXECUTION_KEY, DEFAULT_ASYNC_EXECUTION); int threadNumber_ = configThreadNumber <= 0 ? configThreadNumber : Runtime.getRuntime().availableProcessors(); // ThreadFactory threadFactory = new ThreadFactory() { public Thread newThread(Runnable runable) { Thread t = new Thread(runable, "Forum-Thread"); t.setPriority(threadPriority); return t; } }; // if (configAsyncExecution) { executor = new ThreadPoolExecutor(threadNumber_, threadNumber_, keepAliveTime, TimeUnit.SECONDS, workQueue, threadFactory); ((ThreadPoolExecutor) executor).allowCoreThreadTimeOut(true); } else { executor = new DirectExecutor(); } // this.ecs = new ExecutorCompletionService(executor); } public void addTask(Callable callable) { ecs.submit(callable); } public void waitCompletionFinished() { try { if (executor instanceof ExecutorService) { ((ExecutorService) executor).awaitTermination(1, TimeUnit.SECONDS); } } catch (InterruptedException e) { throw new RuntimeException(e); } } public boolean shutdownNow() { boolean isDone = true; Future<?> f; while (ecs != null && (f = ecs.poll()) != null) { isDone &= f.cancel(true); } return isDone; } public boolean isAsync() { return this.configAsyncExecution; } private class DirectExecutor implements Executor { public void execute(final Runnable runnable) { if (Thread.interrupted()) throw new RuntimeException(); runnable.run(); } } }