Netty 3 MemoryAwareThreadPoolExecutor执行顺序异常问题咨询
问题原因分析及解决方案
首先得明确一个关键误区:Netty 3的MemoryAwareThreadPoolExecutor并不是为任务优先级排序设计的,它的核心职责是控制线程池的内存占用上限——通过你自定义的MyObjectSizeEstimator计算每个任务的内存大小,限制队列中所有任务的总内存,避免内存溢出,但它不会改变任务的执行顺序。
为什么你的代码执行顺序是随机的?
你的代码里设置了核心线程数为16,而任务只有10个——这意味着所有任务提交后会立即被分配给不同的核心线程并行执行,任务的启动顺序完全由JVM的线程调度器决定,所以你看到的输出顺序是随机的。哪怕你用了MemoryAwareThreadPoolExecutor,它也不会干预线程调度的顺序,只是在内存占用超过阈值时拒绝新任务。
如何实现“优先执行数据量大的任务”?
要实现这个需求,你需要结合优先级队列和可比较的任务类,让线程池从队列中优先取出数据量大的任务执行。具体修改如下:
1. 修改MyRunnable实现Comparable接口
让任务可以按数据长度倒序排序(数据量大的排在队列前面):
class MyRunnable implements Runnable, Comparable<MyRunnable> { private final byte[] data; public byte[] getData() { return data; } public MyRunnable(byte[] data) { this.data = data; } public void run() { String dataString = new String(data, 0, data.length); System.out.println("Started processing data " + dataString); try { TimeUnit.MILLISECONDS.sleep(3000); } catch (InterruptedException ie){ ie.printStackTrace(); } System.out.println("Done processing data " + dataString); } @Override public int compareTo(MyRunnable o) { // 按数据长度倒序,确保大任务排在队列前面 return Integer.compare(o.getData().length, this.getData().length); } }
2. 给线程池指定优先级队列
MemoryAwareThreadPoolExecutor有一个重载构造方法,可以自定义任务队列。我们使用PriorityBlockingQueue(优先级阻塞队列)来替代默认的FIFO队列:
ThreadPoolExecutor pool = new MemoryAwareThreadPoolExecutor( 1, // 核心线程数设为1,确保任务先进入队列排队 16, // 最大线程数 65536, 1048576, 30, TimeUnit.SECONDS, new MyObjectSizeEstimator(), Executors.defaultThreadFactory(), new PriorityBlockingQueue<Runnable>() // 使用优先级队列 );
关键说明
- 把核心线程数设为1(或小于任务总数)是为了让任务先进入优先级队列,而不是直接被核心线程执行。如果核心线程数大于任务数,任务会被立即分配执行,优先级队列的排序逻辑就起不到作用了。
PriorityBlockingQueue会自动根据MyRunnable的compareTo方法排序,线程池每次从队列头部取出优先级最高的任务执行。
验证效果
修改后运行代码,你会看到数据量大的任务(比如末尾的i=9对应的任务)会被优先启动执行,严格按照数据长度从大到小的顺序处理。
内容的提问来源于stack exchange,提问作者user51
相关产品推荐
相关产品推荐

