private long prepareCaches(boolean repositioned) {
        long curr = mCacheTimer.currMillisecond;
        long end = curr + mContext.mDanmakuFactory.MAX_DANMAKU_DURATION * mScreenSize;
        if (end < mTimer.currMillisecond) {
          return 0;
        }
        long startTime = SystemClock.uptimeMillis();
        IDanmakus danmakus = null;
        int tryCount = 0;
        boolean hasException = false;
        do {
          try {
            danmakus = danmakuList.subnew(curr, end);
          } catch (Exception e) {
            hasException = true;
            SystemClock.sleep(10);
          }
        } while (++tryCount < 3 && danmakus == null && hasException);
        if (danmakus == null) {
          mCacheTimer.update(end);
          return 0;
        }
        BaseDanmaku first = danmakus.first();
        BaseDanmaku last = danmakus.last();
        if (first == null || last == null) {
          mCacheTimer.update(end);
          return 0;
        }
        long deltaTime = first.time - mTimer.currMillisecond;
        long sleepTime = 30 + 10 * deltaTime / mContext.mDanmakuFactory.MAX_DANMAKU_DURATION;
        sleepTime = Math.min(100, sleepTime);
        if (repositioned) {
          sleepTime = 0;
        }

        IDanmakuIterator itr = danmakus.iterator();
        BaseDanmaku item = null;
        long consumingTime = 0;
        int orderInScreen = 0;
        int currScreenIndex = 0;
        int sizeInScreen = danmakus.size();
        //                String message = "";
        while (!mPause && !mCancelFlag) {
          boolean hasNext = itr.hasNext();
          if (!hasNext) {
            //                        message = "break at not hasNext";
            break;
          }
          item = itr.next();

          if (last.time < mTimer.currMillisecond) {
            //                        message = "break at last.time < mTimer.currMillisecond";
            break;
          }

          if (item.hasDrawingCache()) {
            continue;
          }

          if (repositioned == false && (item.isTimeOut() || !item.isOutside())) {
            continue;
          }

          if (!item.hasPassedFilter()) {
            mContext.mDanmakuFilters.filter(
                item, orderInScreen, sizeInScreen, null, true, mContext);
          }

          // Log.e("prepareCache", currScreenIndex+","+orderInScreen+"," + item.time+"skip:"+skip);
          if (item.priority == 0 && item.isFiltered()) {
            continue;
          }

          if (item.getType() == BaseDanmaku.TYPE_SCROLL_RL) {
            // 同屏弹幕密度只对滚动弹幕有效
            int screenIndex =
                (int) ((item.time - curr) / mContext.mDanmakuFactory.MAX_DANMAKU_DURATION);
            if (currScreenIndex == screenIndex) orderInScreen++;
            else {
              orderInScreen = 0;
              currScreenIndex = screenIndex;
            }
          }

          if (!repositioned) {
            try {
              synchronized (mDrawingNotify) {
                mDrawingNotify.wait(sleepTime);
              }
            } catch (InterruptedException e) {
              e.printStackTrace();
              break;
            }
          }

          // build cache
          if (buildCache(item, false) == RESULT_FAILED) {
            // message = "break at build failed";
            break;
          }

          if (!repositioned) {
            consumingTime = SystemClock.uptimeMillis() - startTime;
            if (consumingTime >= DanmakuFactory.COMMON_DANMAKU_DURATION * mScreenSize) {
              //                            message = "break at consumingTime out:" + consumingTime;
              break;
            }
          }
        }
        consumingTime = SystemClock.uptimeMillis() - startTime;
        if (item != null) {
          mCacheTimer.update(item.time);
          // Log.i("cache","stop at :"+item.time+","+count+",size:"+danmakus.size()+","+message);
        } else {
          mCacheTimer.update(end);
        }
        return consumingTime;
      }