/******************************************************************************* * Copyright (c) MOBAC developers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 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 mobac.gui.mapview; //License: GPL. Copyright 2008 by Jan Peter Stotz import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import mobac.program.tilestore.berkeleydb.DelayedInterruptThread; import org.apache.log4j.Logger; public class JobDispatcher implements ThreadFactory, RejectedExecutionHandler { private static final Logger log = Logger.getLogger(JobDispatcher.class); private static final JobDispatcher INSTANCE = new JobDispatcher(); private static final int WORKER_THREAD_MAX_COUNT = 5; /** * Specifies the time span in seconds that a worker thread waits for new jobs to perform. If the time span has * elapsed the worker thread terminates itself. Only the first worker thread works differently, it ignores the * timeout and will never terminate itself. */ private static final int WORKER_THREAD_TIMEOUT = 30; /** * @return the singleton instance of the {@link JobDispatcher} */ public static JobDispatcher getInstance() { return INSTANCE; } private int WORKER_THREAD_ID = 1; private final BlockingQueue<Runnable> jobQueue; private final ThreadPoolExecutor executor; /** * Removes all jobs from the queue that are currently not being processed. */ public void cancelOutstandingJobs() { jobQueue.clear(); } private JobDispatcher() { jobQueue = new LinkedBlockingQueue<Runnable>(); executor = new ThreadPoolExecutor(WORKER_THREAD_MAX_COUNT, WORKER_THREAD_MAX_COUNT, WORKER_THREAD_TIMEOUT, TimeUnit.SECONDS, jobQueue, this, this); executor.allowCoreThreadTimeOut(true); } public void addJob(Runnable job) { executor.execute(job); } public Thread newThread(Runnable r) { int id; synchronized (this) { id = WORKER_THREAD_ID++; } log.trace("New map preview worker thread created with id=" + id); return new DelayedInterruptThread(r, "Map preview thread " + id); } public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { log.error("Map preview job rejected: " + r); } }