class DownloadCall extends NamedRunnable implements Comparable<DownloadCall> {

    public boolean cancel() {
        synchronized (this) {
            if (canceled) return false;
            if (finishing) return false;
            this.canceled = true;
        }

        final long startCancelTime = SystemClock.uptimeMillis();

        OkDownload.with().downloadDispatcher().flyingCanceled(this);

        final DownloadCache cache = this.cache;
        if (cache != null) cache.setUserCanceled();

        // ArrayList#clone is not a thread safe operation,
        // so chains#size may > chains#elementData.length and this will cause
        // ConcurrentModificationException during iterate the ArrayList(ArrayList#next).
        // This is a reproduce example:
        // https://repl.it/talk/share/ConcurrentModificationException/18566.
        // So don't use clone anymore.
        final Object[] chains = blockChainList.toArray();
        if (chains == null || chains.length == 0) {
            if (currentThread != null) {
                Util.d(TAG,
                        "interrupt thread with cancel operation because of chains are not running "
                                + task.getId());
                currentThread.interrupt();
            }
        } else {
            for (Object chain : chains) {
                if (chain instanceof DownloadChain) {
                    ((DownloadChain) chain).cancel();
                }
            }
        }

        if (cache != null) cache.getOutputStream().cancelAsync();

        Util.d(TAG, "cancel task " + task.getId() + " consume: " + (SystemClock
                .uptimeMillis() - startCancelTime) + "ms");
        return true;
    }

    private  DownloadCall(DownloadTask task, boolean asyncExecuted, @NonNull DownloadStore store);
      DownloadCall(DownloadTask task, boolean asyncExecuted,
                 @NonNull ArrayList<DownloadChain> runningBlockList,
                 @NonNull DownloadStore store);

}