/** * Copyright 2013 Akshay Jain (akshay.jain.7983@gmail.com) * * This file is part of PriortyExecutorService. * * PriortyExecutorService is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * PriortyExecutorService 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with PriortyExecutorService. If not, see <http://www.gnu.org/licenses/>. */ package com.util.concurrent; import java.util.Comparator; import java.util.concurrent.BlockingDeque; import java.util.concurrent.Callable; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.RunnableFuture; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This Executor queues up the tasks as per their set priorities. It not only * queues up tasks as per their priorities but also sets those priorities to the * Worker thread assigned for the task as well. * * @author Akshay Jain * */ public class PriorityThreadPoolExecutor extends ThreadPoolExecutor implements PriorityExecutorService { private final BlockingDeque<Runnable> workQueue; private static final RejectedExecutionHandler defaultHandler = new ThreadPoolExecutor.AbortPolicy(); private static final Logger logger = LoggerFactory.getLogger(PriorityThreadPoolExecutor.class); public PriorityThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, Executors.defaultThreadFactory(), defaultHandler); } public PriorityThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, ThreadFactory threadFactory) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, threadFactory, defaultHandler); } public PriorityThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, RejectedExecutionHandler handler) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, Executors.defaultThreadFactory(), handler); } @SuppressWarnings({ "unchecked", "rawtypes" }) public PriorityThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, ThreadFactory threadFactory, RejectedExecutionHandler handler) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, new PriorityBlockingDeque<Runnable>(corePoolSize, new PriorityFutureTaskComparator()), threadFactory, handler); this.workQueue = (BlockingDeque<Runnable>) super.getQueue(); } public Future<?> submit(Runnable task) { return this.submit(task, Thread.NORM_PRIORITY); } public <T> Future<T> submit(Runnable task, T result) { return this.submit(task, result, Thread.NORM_PRIORITY); } public <T> Future<T> submit(Callable<T> task) { return this.submit(task, Thread.NORM_PRIORITY); } public Future<?> submit(Runnable task, int priority) { if (task == null) throw new NullPointerException(); logger.debug("CASSANDRA TEAM: priority of the task is " + priority); RunnableFuture<Object> ftask = newPriorityTaskFor(task, null, priority); execute(ftask); return ftask; } public <T> Future<T> submit(Runnable task, T result, int priority) { if (task == null) throw new NullPointerException(); RunnableFuture<T> ftask = newPriorityTaskFor(task, result, priority); execute(ftask); return ftask; } public <T> Future<T> submit(Callable<T> task, int priority) { if (task == null) throw new NullPointerException(); RunnableFuture<T> ftask = newPriorityTaskFor(task, priority); execute(ftask); return ftask; } protected <T> RunnableFuture<T> newPriorityTaskFor(Runnable runnable, T value, int priority) { return new PriorityFutureTask<T>(runnable, value, priority); } protected <T> RunnableFuture<T> newPriorityTaskFor(Callable<T> callable, int priority) { return new PriorityFutureTask<T>(callable, priority); } @SuppressWarnings("rawtypes") public int getLeastPriority() { PriorityFutureTask task = ((PriorityFutureTask) this.workQueue.peekLast()); return task != null ? task.getPriority() : Integer.MIN_VALUE; } @SuppressWarnings("rawtypes") public int getHighestPriority() { PriorityFutureTask task = ((PriorityFutureTask) this.workQueue.peekFirst()); return task != null ? task.getPriority() : Integer.MAX_VALUE; } /** * makes best possible effort to change priorities but does not guarantee * the same. */ @Override public void changePriorities(int fromPriority, int toPriority) { if (fromPriority < Thread.MIN_PRIORITY || fromPriority > Thread.MAX_PRIORITY || toPriority < Thread.MIN_PRIORITY || toPriority > Thread.MAX_PRIORITY || fromPriority == toPriority) throw new IllegalArgumentException("Invalid from/to priority values"); PriorityFutureTask<?>[] tasks = this.workQueue.toArray(new PriorityFutureTask<?>[0]); for (PriorityFutureTask<?> task : tasks) { if (task.getPriority() == fromPriority) if (this.workQueue.remove(task)) { task.setPriority(toPriority); this.workQueue.offer(task); } } } @SuppressWarnings("rawtypes") private static class PriorityFutureTaskComparator<T extends PriorityFutureTask> implements Comparator<T> { @Override public int compare(T t1, T t2) { return t2.getPriority() - t1.getPriority(); } } }