public synchronized void scheduleFlush(List<Integer> regionIds) {
    AtomicInteger remainToFlush = new AtomicInteger(BATCH_FLUSH_SUBTREE);
    for (int regionId : regionIds) {
      if (flushingRegionSet.contains(regionId)) {
        continue;
      }
      flushingRegionSet.add(regionId);
      workerPool.submit(
          () -> {
            CachedMTreeStore store = regionToStore.get(regionId);
            if (store == null) {
              // store has been closed
              return;
            }
            LockManager lockManager = store.getLockManager();
            lockManager.globalReadLock();
            if (!regionToStore.containsKey(regionId)) {
              // double check store have not been closed
              return;
            }
            try {

              executeFlush(store, regionId, remainToFlush);
            } finally {
              lockManager.globalReadUnlock();
            }
          });
      if (remainToFlush.get() <= 0) {
        break;
      }
    }
  }
Select some subtrees to flush. The subtrees are selected from the MTreeStore by the sequence of
the regionIds. The number of subtrees to flush is determined by parameter {@link
Scheduler#BATCH_FLUSH_SUBTREE}. It will return asynchronously. If worker pool is full, the task
will be discarded directly.

@param regionIds determine the MTreeStore to select subtrees, the head of the list is the first
    MTreeStore to select subtrees
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/pbtree/flush/Scheduler.java