与文档相关。
来自JCIP:
执行 政策 </跨度> 指定 “任务的内容,地点,时间和方式” 执行,包括: … 应该以什么顺序执行任务(FIFO,LIFO,优先级
你可以指定一个 ThreadFactory 在里面 ThreadPoolExecutor 构造函数(或 Executors 工厂方法)。这允许您为执行程序提供给定线程优先级的线程。
ThreadFactory
ThreadPoolExecutor
Executors
要为不同的作业获取不同的线程优先级,您需要将它们发送给具有不同线程工厂的执行程序。
您可以将ThreadPoolExecutor与优先级阻塞队列一起使用 如何使用ThreadPoolExecutor和自定义任务实现PriorityBlockingQueue
只是想为这次讨论增添一点贡献。我实现了这个 ReorderingThreadPoolExecutor 为了一个非常特定的目的,它能够在我想要的时候明确地将执行者的BlockingQueue(在本例中为LinkedBlockingDeque)带到前面,而不必处理优先级(这可能导致死锁并且无论如何都是固定的)。
我正在使用它来管理(在Android应用程序内部)我必须下载许多在长列表视图中显示的图像的情况。每当用户快速向下滚动时,执行程序队列就会充满图像下载请求:通过移动队列顶部的最新部分,我在加载实际在屏幕上的图像时取得了更好的性能,延迟了下载以后可能需要的那些。请注意,我使用内部并发映射键(可以像图像URL字符串一样简单)将任务添加到执行程序,以便稍后可以检索它们以进行重新排序。
还有很多其他方法可以做同样的事情,也许它过于复杂,但它运行良好,而且他的Android SDK中的Facebook在自己的工作线程队列中做了类似的事情。
随意查看代码并给我建议,它在Android项目中,但剥离一些日志和注释会使类纯Java 6。
这里的想法是在执行程序中使用PriorityBlockingQueue。为了这:
首先,您需要优先考虑您的未来:
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(); } }
接下来,您需要定义比较器,以正确排序优先级期货:
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); } } }
接下来让我们假设我们有一个冗长的工作:
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; } }
然后,为了优先执行这些作业,代码将如下所示:
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); } } }
这是很多代码,但这几乎是实现这一目标的唯一方法。
在我的机器上输出如下:
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
你可以实现自己的ThreadFactory并在ThreadPoolExecutor中设置它,如下所示:
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1, numOfWorkerThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); threadPool.setThreadFactory(new OpJobThreadFactory(Thread.NORM_PRIORITY-2));
我的OpJobThreadFactory如下所示:
public final static class OpJobThreadFactory implements ThreadFactory { private int priority; private boolean daemon; private final String namePrefix; private static final AtomicInteger poolNumber = new AtomicInteger(1); private final AtomicInteger threadNumber = new AtomicInteger(1); public OpJobThreadFactory(int priority) { this(priority, true); } public OpJobThreadFactory(int priority, boolean daemon) { this.priority = priority; this.daemon = daemon; namePrefix = "jobpool-" +poolNumber.getAndIncrement() + "-thread-"; } @Override public Thread newThread(Runnable r) { Thread t = new Thread(r, namePrefix + threadNumber.getAndIncrement()); t.setDaemon(daemon); t.setPriority(priority); return t; } }