class TaskSplitter {

        final HgScanQuery scanQuery;
        final BiFunction<HgScanQuery, KvCloseableIterator, Boolean> taskHandler;
        private KvBatchScannerMerger notifier;
        private Iterator<HgOwnerKey> prefixItr;
        private int maxTaskSize = 0; // 最大并行任务数
        private int maxBatchSize = PropertyUtil.getInt("net.kv.scanner.batch.size", 1000);
        // 每批次最大点数量
        private volatile boolean finished = false;
        private volatile boolean splitting = false;
        private volatile int nextKeySerialNo = 1;

        public TaskSplitter(HgScanQuery scanQuery,
                            BiFunction<HgScanQuery, KvCloseableIterator, Boolean> handler) {
            this.scanQuery = scanQuery;
            this.taskHandler = handler;
            if (scanQuery.getScanMethod() == HgScanQuery.ScanMethod.PREFIX) {
                if (scanQuery.getPrefixItr() != null) {
                    prefixItr = scanQuery.getPrefixItr();
                } else {
                    prefixItr = scanQuery.getPrefixList().listIterator();
                }
            }
        }

        public void setNotifier(KvBatchScannerMerger notifier) {
            this.notifier = notifier;
        }

        public boolean isFinished() {
            return finished;
        }

        /**
         * 评估最大任务数
         */
        private void evaluateMaxTaskSize() {<FILL_FUNCTION_BODY>}

        /**
         * 拆分任务，任务拆分为多个grpc请求
         */
        public void splitTask() {
            if (this.finished || this.splitting) {
                return;
            }
            synchronized (this) {
                if (this.finished) {
                    return;
                }
                this.splitting = true;
                if (scanQuery.getScanMethod() == HgScanQuery.ScanMethod.PREFIX) {
                    if (prefixItr.hasNext() &&
                        (maxTaskSize == 0 || notifier.getScannerCount() < maxTaskSize)) {
                        List<HgOwnerKey> keys = new ArrayList<>(maxBatchSize);
                        for (int i = 0; i < maxBatchSize && prefixItr.hasNext(); i++) {
                            keys.add(prefixItr.next().setSerialNo(nextKeySerialNo++));
                        }
                        taskHandler.apply(
                                HgScanQuery.prefixOf(scanQuery.getTable(), keys,
                                                     scanQuery.getOrderType()), this.notifier);
                        // 评估最大任务数
                        evaluateMaxTaskSize();
                        if (this.notifier.getScannerCount() < this.maxTaskSize) {
                            splitTask(); // 未达到最大任务数，继续拆分
                        }
                    }
                    this.finished = !prefixItr.hasNext();
                } else {
                    taskHandler.apply(scanQuery, this.notifier);
                    this.finished = true;
                }
                this.splitting = false;
            }
        }

        public synchronized void close() {
            finished = true;
        }
    }

            if (maxTaskSize == 0) { // 根据第一批次任务，得到store数量，然后计算最大任务数
                if (scanQuery.getOrderType() == ScanOrderType.ORDER_STRICT) {
                    maxTaskSize = 1; // 点排序，每台机器一个流, 所有store流结束后才能启动其他流
                } else {
                    maxTaskSize = this.notifier.getScannerCount() * maxTaskSizePerStore;
                }
                maxBatchSize = this.notifier.getScannerCount() * maxBatchSize; // 每台机器最多1000条

                /*
                 * Limit少于10000时启动一个流，节省网络带宽
                 */
                if (scanQuery.getLimit() < maxBatchSize * 30L) {
                    maxTaskSize = 1;
                }
            }
        
<no_super_class>