@Override
      public void run() {
        final int bufferSize = 1024;
        final byte[] buf = new byte[bufferSize];
        int readlen;
        int readSize = bufferSize;
        long total = 0;
        try {
          while ((readlen = _stream.read(buf, 0, readSize)) != 0) {
            _file.write(buf, 0, readlen);
            _handler.sendProgressUpdateMessage(readlen);
            total += readlen;

            if (total >= _readCap) {
              break;
            }

            final int remain = (int) (_readCap - total);
            if (remain < bufferSize) {
              readSize = remain;
            }
          }
        } catch (final IOException e) {
          e.printStackTrace();
        } finally {
          try {
            _stream.close();
          } catch (final Exception e) {
            e.printStackTrace();
          }
          try {
            _file.close();
          } catch (final Exception e) {
            e.printStackTrace();
          }
        }

        synchronized (Downloader.this) {
          _threadFinishedCount++;
          Downloader.this.notify();
        }
      }
    @Override
    public void run() {
      _wifiLock.acquire();
      final String asxUrl = _episode.getAsxUrl();
      AsxModel asx;
      try {
        asx = AsxModel.createModelFromUrl(asxUrl);
      } catch (IOException e) {
        e.printStackTrace();
        _handler.sendDownloadFailedMessage();
        return;
      }
      final List<AsxEntryModel> entries = asx.getEntries();
      final String[] playlist = new String[entries.size()];
      for (int i = 0; i < playlist.length; i++) {
        final AsxEntryModel entry = entries.get(i);
        final String ref = entry.getRef();
        playlist[i] = ref;
      }

      long totalSize = 10L;
      for (final String url : playlist) {
        try {
          final MMSInputStream mmsStream = new MMSInputStream(url);
          totalSize += mmsStream.getSize();
          mmsStream.close();
        } catch (final Exception e) {
          Log.e(TAG, e.getMessage());
          _handler.sendDownloadFailedMessage();
          _wifiLock.release();
          return;
        }
      }
      _handler.sendTotalSizeUpdateMessage(totalSize);

      for (final String url : playlist) {
        _threadFinishedCount = 0;
        try {
          final MMSInputStream mmsStream = new MMSInputStream(url);
          final long size = mmsStream.getSize();
          final double length = mmsStream.getLength();

          final List<FileOutputStream> files;
          final String filePath;
          try {
            final String externalStorageState = Environment.getExternalStorageState();
            if (externalStorageState.equals(Environment.MEDIA_REMOVED)) {
              _handler.sendDownloadFailedMessage();
              _wifiLock.release();
              mmsStream.close();
              return;
            }
            final File sdCardRoot = Environment.getExternalStorageDirectory();
            final String sdCardPath = sdCardRoot.getPath();
            final File rthkFolder = new File(sdCardPath + "/RthkArchivePlayer");

            if (!rthkFolder.exists()) {
              rthkFolder.mkdirs();
            }

            final String rthkPath = rthkFolder.getPath();
            final String filename = URLEncoder.encode(url, "utf-8");
            filePath = rthkPath + "/" + filename;

            files = new ArrayList<FileOutputStream>(_threadNum);
            String ext = "";
            for (int i = 0; i < _threadNum; i++, ext = ".part" + i) {
              final FileOutputStream stream = new FileOutputStream(filePath + ext);
              files.add(stream);
            }

          } catch (final Exception e) {
            Log.e(TAG, e.getMessage());
            _handler.sendDownloadFailedMessage();
            _wifiLock.release();
            return;
          }

          int streamNum = 0;
          final long stepSize = size / _threadNum;

          long startPos = -1L;
          long readCap = -1L;
          DownloadThread downloadThread = null;

          for (final FileOutputStream file : files) {
            final MMSInputStream stream;
            if (streamNum == 0) {
              stream = mmsStream;
              startPos = 0L;
            } else {
              stream = new MMSInputStream(url);
              final long pos = stream.seekByte(stepSize * streamNum);
              readCap = pos - startPos;
              downloadThread.setReadCapacity(readCap);
              downloadThread.start();
              startPos = pos;
            }

            downloadThread = new DownloadThread(stream, file, streamNum);

            streamNum++;

            if (streamNum == _threadNum) {
              downloadThread.setReadCapacity(size * 2);
              downloadThread.start();
            }
          }

          synchronized (this) {
            while (_threadFinishedCount < _threadNum) {
              try {
                wait();
              } catch (final InterruptedException e) {
                e.printStackTrace();
              }
            }
          }

          final FileOutputStream baseFile = new FileOutputStream(filePath, true);
          ;
          for (int i = 1; i < _threadNum; i++) {
            final String path = filePath + ".part" + i;
            try {
              final File file = new File(path);
              final FileInputStream inputStream = new FileInputStream(file);
              final byte[] buffer = new byte[1024];
              int read = 0;
              while ((read = inputStream.read(buffer)) > 0) {
                baseFile.write(buffer, 0, read);
              }
              inputStream.close();
              file.delete();
            } catch (final IOException e) {
              Log.e(TAG, e.getMessage());
            }
          }
          baseFile.close();

          final AsfFileDbAdapter dbAdapter = new AsfFileDbAdapter(_context);
          dbAdapter.open();
          dbAdapter.createFile(url, filePath, length, size);
          dbAdapter.close();
        } catch (final IOException e) {
          Log.e(TAG, e.getMessage());
          _handler.sendDownloadFailedMessage();
          _wifiLock.release();
          return;
        }
      }
      _wifiLock.release();
      _handler.sendDownloadSuccessMessage();
    }