Java Executors:如何设置任务优先级?

Rom*_*man 38 java concurrency multithreading executor thread-priority

是否有可能为Executors执行的任务设置优先级?我在JCIP中发现了一些关于它可能的陈述,但我找不到任何例子,我找不到任何与文档相关的内容.

来自JCIP:

执行策略指定任务执行的"内容,位置,时间和方式",包括:

  • ...
  • 应该以什么顺序执行任务(FIFO,LIFO,优先顺序)?
  • ...

UPD:我意识到我不确切地问我想问什么.我真正想要的是:

如何使用/模拟thread.setPriority()执行程序框架设置线程优先级(即什么)?

Dav*_*ers 60

目前,Executor接口的唯一具体实现是ThreadPoolExecutorScheduledThreadpoolExecutor

您应该使用构造函数创建实例,而不是使用实用程序/工厂类Executors.

您可以将BlockingQueue传递给ThreadPoolExecutor的构造函数.

作为BlockingQueue的一个实现,PriorityBlockingQueue允许您将Comparator传递给构造函数,这样您就可以决定执行的顺序.

  • +1 PriorityBlockingQueue是要走的路.您可以实现比较器或使任务本身可比较. (4认同)
  • 这篇文章是一个很好的参考:http://binkley.blogspot.fr/2009/04/jumping-work-queue-in-executor.html (3认同)

Sta*_*kyy 40

这里的想法是在执行程序中使用PriorityBlockingQueue.为了这:

  • 创建一个比较我们未来的比较器.
  • 为Future创建一个代理来保持优先级.
  • 覆盖'newTaskFor'以包装代理中的每个未来.

首先,您需要优先考虑您的未来:

    class PriorityFuture<T> implements RunnableFuture<T> {

    private RunnableFuture<T> src;
    private int priority;

    public PriorityFuture(RunnableFuture<T> other, int priority) {
        this.src = other;
        this.priority = priority;
    }

    public int getPriority() {
        return priority;
    }

    public boolean cancel(boolean mayInterruptIfRunning) {
        return src.cancel(mayInterruptIfRunning);
    }

    public boolean isCancelled() {
        return src.isCancelled();
    }

    public boolean isDone() {
        return src.isDone();
    }

    public T get() throws InterruptedException, ExecutionException {
        return src.get();
    }

    public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
        return src.get();
    }

    public void run() {
        src.run();
    }
}
Run Code Online (Sandbox Code Playgroud)

接下来,您需要定义比较器,以正确排序优先级期货:

class PriorityFutureComparator implements Comparator<Runnable> {
    public int compare(Runnable o1, Runnable o2) {
        if (o1 == null && o2 == null)
            return 0;
        else if (o1 == null)
            return -1;
        else if (o2 == null)
            return 1;
        else {
            int p1 = ((PriorityFuture<?>) o1).getPriority();
            int p2 = ((PriorityFuture<?>) o2).getPriority();

            return p1 > p2 ? 1 : (p1 == p2 ? 0 : -1);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

接下来让我们假设我们有一个冗长的工作:

class LenthyJob implements Callable<Long> {
    private int priority;

    public LenthyJob(int priority) {
        this.priority = priority;
    }

    public Long call() throws Exception {
        System.out.println("Executing: " + priority);
        long num = 1000000;
        for (int i = 0; i < 1000000; i++) {
            num *= Math.random() * 1000;
            num /= Math.random() * 1000;
            if (num == 0)
                num = 1000000;
        }
        return num;
    }

    public int getPriority() {
        return priority;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,为了优先执行这些作业,代码将如下所示:

public class TestPQ {

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        int nThreads = 2;
        int qInitialSize = 10;

        ExecutorService exec = new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,
                new PriorityBlockingQueue<Runnable>(qInitialSize, new PriorityFutureComparator())) {

            protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
                RunnableFuture<T> newTaskFor = super.newTaskFor(callable);
                return new PriorityFuture<T>(newTaskFor, ((LenthyJob) callable).getPriority());
            }
        };

        for (int i = 0; i < 20; i++) {
            int priority = (int) (Math.random() * 100);
            System.out.println("Scheduling: " + priority);
            LenthyJob job = new LenthyJob(priority);
            exec.submit(job);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是很多代码,但这几乎是实现这一目标的唯一方法.

在我的机器上输出如下:

Scheduling: 39
Scheduling: 90
Scheduling: 88
Executing: 39
Scheduling: 75
Executing: 90
Scheduling: 15
Scheduling: 2
Scheduling: 5
Scheduling: 24
Scheduling: 82
Scheduling: 81
Scheduling: 3
Scheduling: 23
Scheduling: 7
Scheduling: 40
Scheduling: 77
Scheduling: 49
Scheduling: 34
Scheduling: 22
Scheduling: 97
Scheduling: 33
Executing: 2
Executing: 3
Executing: 5
Executing: 7
Executing: 15
Executing: 22
Executing: 23
Executing: 24
Executing: 33
Executing: 34
Executing: 40
Executing: 49
Executing: 75
Executing: 77
Executing: 81
Executing: 82
Executing: 88
Executing: 97
Run Code Online (Sandbox Code Playgroud)

  • 虽然*接受的答案*确实回答了这个问题,但这个答案提供了一个可行的解决方案。多谢。 (3认同)