Укажите выполнение порядка задачи в Java

Я много искал, но не нашел решения. Я использую пул потоков java таким образом:

ExecutorService c = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; ++i) {
  c.execute(new MyTask(i));
}

Таким образом, задачи выполняются в последовательном порядке (как в очереди). Но мне нужно изменить стратегию «выбрать следующую задачу». Поэтому я хочу назначить каждой задаче, указать приоритет (это не приоритет потока) и выполнить задачи, соответствующие этим приоритетам. Поэтому, когда исполнитель завершил другую задачу, он выбирает следующую задачу как задачу с максимальным приоритетом. Он описывает общую проблему. Может быть, есть более простой подход, не учитывающий приоритеты. Он выбирает последнюю добавленную задачу как следующую для выполнения вместо первой добавленной. Грубо говоря, FixedThreadPool использует стратегию FIFO. Могу ли я использовать, например, стратегию LIFO?


person Rustam Iuzmukhametov    schedule 04.10.2012    source источник


Ответы (2)


Вы можете использовать PriorityBlockingQueue, чтобы указать очередь в ThreadPoolExecutor.

public class PriorityExecutor extends ThreadPoolExecutor {

    public PriorityExecutor(int corePoolSize, int maximumPoolSize,
            long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }
    //Utitlity method to create thread pool easily
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new PriorityExecutor(nThreads, nThreads, 0L,
                TimeUnit.MILLISECONDS, new PriorityBlockingQueue<Runnable>());
    }
    //Submit with New comparable task 
    public Future<?> submit(Runnable task, int priority) {
        return super.submit(new ComparableFutureTask(task, null, priority));
    }
    //execute with New comparable task 
    public void execute(Runnable command, int priority) {
        super.execute(new ComparableFutureTask(command, null, priority));
    }
}

Определите ComparableFutureTask для сравнения по приоритету.

class ComparableFutureTask<T> extends FutureTask<T>
        implements
            Comparable<ComparableFutureTask<T>> {

    volatile int priority = 0;

    public ComparableFutureTask(Runnable runnable, T result, int priority) {
        super(runnable, result);
        this.priority = priority;
    }
    public ComparableFutureTask(Callable<T> callable, int priority) {
        super(callable);
        this.priority = priority;
    }
    @Override
    public int compareTo(ComparableFutureTask<T> o) {
        return Integer.valueOf(priority).compareTo(o.priority);
    }
  }
person Amit Deshpande    schedule 04.10.2012
comment
Это не может сработать, потому что newTaskFor превратит ComparableFutureTask в FutureTask, что несопоставимо. Вам также необходимо переопределить два newTaskFor метода. - person assylias; 30.05.2013
comment
См. Упрощенный пример в этом сообщении. - person assylias; 30.05.2013
comment
Мое решение упорядочивает задачи по приоритету, но сохраняет порядок отправки с теми же уровнями приоритета: stackoverflow.com/a/42831172/1386911 - person Daniel Hári; 16.03.2017

Конструктор ThreadPoolExecutor принимает BlockingQueue. Вы можете передать очередь как PriorityBlockingQueue. Он не предоставляет никаких прав при заказе, вам необходимо передать настраиваемые компараторы для поддержания порядка.

static BlockingQueue<Task> queue=new PriorityBlockingQueue<Task>(MAXPOOL,new TaskComparator());

static ThreadPoolExecutor threadpool = new ThreadPoolExecutor(30, MAXPOOL, 
        MAXPOOL, TimeUnit.SECONDS, (PriorityBlockingQueue) queue, new mThreadFactory());



class TaskComparator implements Comparator<Task>{
  public int compare(Task t1, Task t2){
    //write you own logic to compare two task.
  }
}
person Subhrajyoti Majumder    schedule 04.10.2012
comment
Хороший пост, за исключением того, что equals возвращает boolean, а compare возвращает int. Я думаю, вы хотели использовать compareTo. - person Tudor; 04.10.2012