class MultiPointOutputStream {

    void runSync() throws IOException {
        Util.d(TAG, "OutputStream start flush looper task[" + task.getId() + "] with "
                + "syncBufferIntervalMills[" + syncBufferIntervalMills + "] " + "syncBufferSize["
                + syncBufferSize + "]");
        runSyncThread = Thread.currentThread();

        long nextParkMills = syncBufferIntervalMills;

        flushProcess();

        while (true) {
            parkThread(nextParkMills);

            inspectStreamState(state);

            // if is no more stream, we will flush all data and quit.
            if (state.isStreamsEndOrChanged()) {
                Util.d(TAG, "runSync state change isNoMoreStream[" + state.isNoMoreStream + "]"
                        + " newNoMoreStreamBlockList[" + state.newNoMoreStreamBlockList + "]");
                if (allNoSyncLength.get() > 0) {
                    flushProcess();
                }

                for (Integer blockIndex : state.newNoMoreStreamBlockList) {
                    final Thread parkedThread = parkedRunBlockThreadMap.get(blockIndex);
                    parkedRunBlockThreadMap.remove(blockIndex);
                    if (parkedThread != null) unparkThread(parkedThread);
                }

                if (state.isNoMoreStream) {
                    final int size = parkedRunBlockThreadMap.size();
                    for (int i = 0; i < size; i++) {
                        final Thread parkedThread = parkedRunBlockThreadMap.valueAt(i);
                        if (parkedThread != null) unparkThread(parkedThread);
                    }
                    parkedRunBlockThreadMap.clear();
                    break;
                } else {
                    continue;
                }
            }

            if (isNoNeedFlushForLength()) {
                nextParkMills = syncBufferIntervalMills;
                continue;
            }

            nextParkMills = getNextParkMillisecond();
            if (nextParkMills > 0) {
                continue;
            }

            flushProcess();
            nextParkMills = syncBufferIntervalMills;
        }

        Util.d(TAG, "OutputStream stop flush looper task[" + task.getId() + "]");
    }

      MultiPointOutputStream(@NonNull final DownloadTask task,
                           @NonNull BreakpointInfo info,
                           @NonNull DownloadStore store,
                           @Nullable Runnable syncRunnable);
    public  MultiPointOutputStream(@NonNull DownloadTask task,
                                  @NonNull BreakpointInfo info,
                                  @NonNull DownloadStore store);

}