blob: 99e8fb21a353af1f6b6c422883ce6e69a0311cd5 [file] [log] [blame]
/*
* ExecutorQueue.java February 2007
*
* Copyright (C) 2007, Niall Gallagher <niallg@users.sf.net>
*
* 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.simpleframework.common.thread;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* The <code>ExecutorQueue</code> object is used to queue tasks in
* a thread pool. This creates a thread pool with no limit to the
* number of tasks that can be enqueued, which ensures that any
* system requesting a task to be executed will not block when
* handing it over, it also means the user must use caution.
*
* @author Niall Gallagher
*
* @see org.simpleframework.common.thread.ConcurrentExecutor
*/
class ExecutorQueue {
/**
* This is the task queue that contains tasks due to execute.
*/
private final BlockingQueue<Runnable> queue;
/**
* This is the actual thread pool implementation used.
*/
private final ThreadPoolExecutor executor;
/**
* This is used to create the pool worker threads.
*/
private final ThreadFactory factory;
/**
* Constructor for the <code>ExecutorQueue</code> object. This is
* used to create a pool of threads that can be used to execute
* arbitrary <code>Runnable</code> tasks. If the threads are
* busy this will simply enqueue the tasks and return.
*
* @param type this is the type of runnable that this accepts
* @param rest this is the number of threads to use in the pool
* @param active this is the maximum size the pool can grow to
*/
public ExecutorQueue(Class type, int rest, int active) {
this(type, rest, active, 120, TimeUnit.SECONDS);
}
/**
* Constructor for the <code>ExecutorQueue</code> object. This is
* used to create a pool of threads that can be used to execute
* arbitrary <code>Runnable</code> tasks. If the threads are
* busy this will simply enqueue the tasks and return.
*
* @param type this is the type of runnable that this accepts
* @param rest this is the number of threads to use in the pool
* @param active this is the maximum size the pool can grow to
* @param duration the duration active threads remain idle for
* @param unit this is the time unit used for the duration
*/
public ExecutorQueue(Class type, int rest, int active, long duration, TimeUnit unit) {
this.queue = new LinkedBlockingQueue<Runnable>();
this.factory = new DaemonFactory(type);
this.executor = new ThreadPoolExecutor(rest, active, duration, unit, queue, factory);
}
/**
* The <code>execute</code> method is used to queue the task for
* execution. If all threads are busy the provided task is queued
* and waits until all current and outstanding tasks are finished.
*
* @param task this is the task to be queued for execution
*/
public void execute(Runnable task) {
executor.execute(task);
}
/**
* This is used to stop the executor by interrupting all running
* tasks and shutting down the threads within the pool. This will
* return once it has been stopped, and no further tasks will be
* accepted by this pool for execution.
*/
public void stop() {
stop(60000);
}
/**
* This is used to stop the executor by interrupting all running
* tasks and shutting down the threads within the pool. This will
* return once it has been stopped, and no further tasks will be
* accepted by this pool for execution.
*
* @param wait the number of milliseconds to wait for it to stop
*/
public void stop(long wait) {
if(!executor.isTerminated()) {
try {
executor.shutdown();
executor.awaitTermination(wait, MILLISECONDS);
} catch(Exception e) {
throw new IllegalStateException("Could not stop pool", e);
}
}
}
}