Android 스 레 드 의 끝,끊 기 및 복구

20716 단어 Android진급 하 다
전환 하 다http://blog.sina.com.cn/s/blog_4c0706560101175r.html
Android 스 레 드 클래스 도 스 레 드 를 걸 고 복구 하 는 공공 방법 을 제공 합 니 다.
final void resume()                                       
//This method is deprecated. Used with deprecated method suspend
final void suspend()
//This method is deprecated. May cause deadlocks

마찬가지 로 불행 하 게 도 설명 을 통 해 우 리 는 이런 방법 들 이 안 드 로 이 드 도 추천 하지 않 고 필자 의 실험 을 통 해 이런 방법 들 도 효과 가 없다 는 것 을 알 수 있다.
Android 의 클래스 는 기본적으로 Object 클래스 에 계승 된다.이런 것 은 안 드 로 이 드 류 의 조상 이 라 고 할 수 있다.안 드 로 이 드 류 를 하나의 생물 계 에 비유한다 면 오 브 젝 트 류 는 애초에 생명 이 태 어 났 을 때의 그 단세포 다.
       우 리 는 Object 류 가 몇 가지 방법 을 제공 한 것 을 발견 할 수 있다.
final void notify()
Causes a thread which is waiting on this object's monitor (by means of calling one of the wait() methods) to be woken
final void notifyAll()
Causes all threads which are waiting on this object's monitor (by means of calling one of the wait() methods) to be woken
final void wait()
Causes the calling thread to wait until another thread calls the notify() or notifyAll() method of this object

설명 을 통 해 알 수 있 듯 이 wait 방법 은 호출 중인 스 레 드 를 대기 상태 로 만 들 수 있 습 니 다.다른 스 레 드 가 이 대상 의 notify 나 notify All 을 호출 할 때 까지,notify 와 notify All 방법 은 대기 중인 스 레 드 를 깨 우 는 데 사 용 됩 니 다.
       마찬가지 로 스 레 드 류 도 Object 류 에 계승 되 지만 스 레 드 류 는 비교적 특수 한 유형 으로 자신 만 의 독립 된 스 택 체제 로 그 방법,파라미터 와 부분 변 수 를 처리 합 니 다.실험 을 통 해 필 자 는 스 레 드 류 가 Object 류 에 계승 되 었 지만 wait 와 notify 방법 으로 스 레 드 를 깨 울 수 없다 는 것 을 발견 했다.상기 동작 을 실현 하려 면 사용자 정의 스 레 드 클래스 에서 Object 대상 을 만 든 다음 에 이 Object 와 관련 된 작업 을 통 해 스 레 드 의 연결 과 깨 워 야 합 니 다.방법 은 다음 과 같다.
1.    사용자 정의 스 레 드 클래스 의 예화 과정 에서 Object 대상 을 만 듭 니 다.
2.    스 레 드 의 상 태 를 기록 할 변 수 를 정의 합 니 다.초기 화 는 가짜 입 니 다.
3.    온라인 프로 세 스 클래스 의 run 함수 의 스 레 드 실행 부분 에서 끈기 있 는 부분 을 찾 아 다음 동작 을 수행 합 니 다.현재 상태 변수 가 가짜(스 레 드 가 걸 려 있 음 을 표시 합 니 다)라면 1 에서 Object 대상 의 wait 방법 으로 현재 스 레 드 를 걸 겠 습 니 다.즉,스 레 드 가 끈기 있 는 위치 에 잠시 멈 추고 불 러 오 면 끈기 있 는 부분 에서 계속 실 행 됩 니 다.
4.    스 레 드 상태 변 수 를 진짜 로 수정 하여 스 레 드 를 걸 수 있 는 방법 을 정의 합 니 다.
5.    스 레 드 를 깨 우 는 방법 을 정의 합 니 다.스 레 드 상태 변 수 를 진짜 로 판단 하면 가짜 로 수정 한 다음 1 중 Object 대상 의 notify All 방법 으로 대상 을 깨 웁 니 다.(notify 방법 도 가능 하지만 사용자 정의 스 레 드 가 많 을 때 잠 금 이 걸 리 기 쉽다).
다시 말 하면 사용자 정의 스 레 드 가 실 행 된 후에 우 리 는 4 가지 방법 으로 스 레 드 를 걸 고 5 가지 방법 으로 스 레 드 를 깨 울 수 있 습 니 다.
class SearchThread extends Thread
   {
      private Object mPauseLock ;
      private boolean mPauseFlag ;   
     
      public SearchThread()
      {
         
          mPauseLock = new Object() ;
          mPauseFlag = false ;
      }
     
      public void onPause()
      {
          synchronized (mPauseLock) {
             mPauseFlag = true;
             }
      }
     
      public void onResume()
      {
          synchronized (mPauseLock) {
             mPauseFlag = false ;
             mPauseLock.notifyAll() ;
             }
      }
            
      private void pauseThread()
      {
          synchronized (mPauseLock) {
             if(mPauseFlag)
             {
                try{
                   mPauseLock.wait() ;
                }catch(Exception e){
                   Log.v("thread", "fails") ;
                }
             }
             }
      }    
 
@Override
      public void run()
    {
       ……
       //---      ,        -----
         for(int i = 0; i < 100; i++)
      {
          pauseThread() ;
          ……
          for(int j = 0; j < 100; j++)
          {
               pauseThread() ;
               ……
          }
}
       //-----end----------
       ……
      }
}

위 에서 말 한 방법 에 따라 XUtis 그림 캐 시 원본 코드 를 뒤 집 었 습 니 다.그림 의 캐 시 는 Lru(최근 알고리즘 사용)를 사용 하고 아래 는 일부 코드 입 니 다.
public class BitmapCache {

    private final int DISK_CACHE_INDEX = 0;

    private LruDiskCache mDiskLruCache;
    private LruMemoryCache mMemoryCache;

    private final Object mDiskCacheLock = new Object();
    private boolean isDiskCacheReadied = false;

    private BitmapGlobalConfig globalConfig;

    /**
     * Creating a new ImageCache object using the specified parameters.
     *
     * @param globalConfig The cache parameters to use to initialize the cache
     */
    public BitmapCache(BitmapGlobalConfig globalConfig) {
        if (globalConfig == null) throw new IllegalArgumentException("globalConfig may not be null");
        this.globalConfig = globalConfig;
    }


    /**
     * Initialize the memory cache
     */
    public void initMemoryCache() {
        if (!globalConfig.isMemoryCacheEnabled()) return;

        // Set up memory cache
        if (mMemoryCache != null) {
            try {
                clearMemoryCache();
            } catch (Throwable e) {
            }
        }
        mMemoryCache = new LruMemoryCache(globalConfig.getMemoryCacheSize()) {
            /**
             * Measure item size in bytes rather than units which is more practical
             * for a bitmap cache
             */
            @Override
            protected int sizeOf(MemoryCacheKey key, Bitmap bitmap) {
                if (bitmap == null) return 0;
                return bitmap.getRowBytes() * bitmap.getHeight();
            }
        };
    }

    /**
     * Initializes the disk cache.  Note that this includes disk access so this should not be
     * executed on the main/UI thread. By default an ImageCache does not initialize the disk
     * cache when it is created, instead you should call initDiskCache() to initialize it on a
     * background thread.
     */
    public void initDiskCache() {
        if (!globalConfig.isDiskCacheEnabled()) return;

        // Set up disk cache
        synchronized (mDiskCacheLock) {
            if (mDiskLruCache == null || mDiskLruCache.isClosed()) {
                File diskCacheDir = new File(globalConfig.getDiskCachePath());
                if (!diskCacheDir.exists()) {
                    diskCacheDir.mkdirs();
                }
                long availableSpace = BitmapCommonUtils.getAvailableSpace(diskCacheDir);
                long diskCacheSize = globalConfig.getDiskCacheSize();
                diskCacheSize = availableSpace > diskCacheSize ? diskCacheSize : availableSpace;
                try {
                    mDiskLruCache = LruDiskCache.open(diskCacheDir, 1, 1, diskCacheSize);
                    mDiskLruCache.setDiskCacheFileNameGenerator(globalConfig.getDiskCacheFileNameGenerator());
                } catch (Throwable e) {
                    mDiskLruCache = null;
                    LogUtils.e(e.getMessage(), e);
                }
            }
            isDiskCacheReadied = true;
            mDiskCacheLock.notifyAll();
        }
    }

 
    public Bitmap downloadBitmap(String uri, BitmapDisplayConfig config, final BitmapUtils.BitmapLoadTask> task) {

        BitmapMeta bitmapMeta = new BitmapMeta();

        OutputStream outputStream = null;
        LruDiskCache.Snapshot snapshot = null;

        try {

            Bitmap bitmap = null;
            // try download to disk
            if (globalConfig.isDiskCacheEnabled()) {
                synchronized (mDiskCacheLock) {
                    // Wait for disk cache to initialize
                    while (!isDiskCacheReadied) {// false   
                        try {
							//         
                            mDiskCacheLock.wait();
                        } catch (Throwable e) {
                        }
                    }

                    if (mDiskLruCache != null) {
                        try {
                            snapshot = mDiskLruCache.get(uri);
                            if (snapshot == null) {
                                LruDiskCache.Editor editor = mDiskLruCache.edit(uri);
                                if (editor != null) {
                                    outputStream = editor.newOutputStream(DISK_CACHE_INDEX);
                                    bitmapMeta.expiryTimestamp = globalConfig.getDownloader().downloadToStream(uri, outputStream, task);
                                    if (bitmapMeta.expiryTimestamp < 0) {
                                        editor.abort();
                                        return null;
                                    } else {
                                        editor.setEntryExpiryTimestamp(bitmapMeta.expiryTimestamp);
                                        editor.commit();
                                    }
                                    snapshot = mDiskLruCache.get(uri);
                                }
                            }
                            if (snapshot != null) {
                                bitmapMeta.inputStream = snapshot.getInputStream(DISK_CACHE_INDEX);
                                bitmap = decodeBitmapMeta(bitmapMeta, config);
                                if (bitmap == null) {
                                    bitmapMeta.inputStream = null;
                                    mDiskLruCache.remove(uri);
                                }
                            }
                        } catch (Throwable e) {
                            LogUtils.e(e.getMessage(), e);
                        }
                    }
                }
            }

            // try download to memory stream
            if (bitmap == null) {
                outputStream = new ByteArrayOutputStream();
                bitmapMeta.expiryTimestamp = globalConfig.getDownloader().downloadToStream(uri, outputStream, task);
                if (bitmapMeta.expiryTimestamp < 0) {
                    return null;
                } else {
                    bitmapMeta.data = ((ByteArrayOutputStream) outputStream).toByteArray();
                    bitmap = decodeBitmapMeta(bitmapMeta, config);
                }
            }

            if (bitmap != null) {
                bitmap = rotateBitmapIfNeeded(uri, config, bitmap);
                addBitmapToMemoryCache(uri, config, bitmap, bitmapMeta.expiryTimestamp);
            }
            return bitmap;
        } catch (Throwable e) {
            LogUtils.e(e.getMessage(), e);
        } finally {
            IOUtils.closeQuietly(outputStream);
            IOUtils.closeQuietly(snapshot);
        }

        return null;
    }
 
    /**
     * Get the bitmap from disk cache.
     *
     * @param uri
     * @param config
     * @return
     */
    public Bitmap getBitmapFromDiskCache(String uri, BitmapDisplayConfig config) {
        if (uri == null || !globalConfig.isDiskCacheEnabled()) return null;
        synchronized (mDiskCacheLock) {
            while (!isDiskCacheReadied) {
                try {
                    mDiskCacheLock.wait();
                } catch (Throwable e) {
                }
            }
            if (mDiskLruCache != null) {
                LruDiskCache.Snapshot snapshot = null;
                try {
                    snapshot = mDiskLruCache.get(uri);
                    if (snapshot != null) {
                        Bitmap bitmap = null;
                        if (config == null || config.isShowOriginal()) {
                            bitmap = BitmapDecoder.decodeFileDescriptor(
                                    snapshot.getInputStream(DISK_CACHE_INDEX).getFD());
                        } else {
                            bitmap = BitmapDecoder.decodeSampledBitmapFromDescriptor(
                                    snapshot.getInputStream(DISK_CACHE_INDEX).getFD(),
                                    config.getBitmapMaxSize(),
                                    config.getBitmapConfig());
                        }

                        bitmap = rotateBitmapIfNeeded(uri, config, bitmap);
                        addBitmapToMemoryCache(uri, config, bitmap, mDiskLruCache.getExpiryTimestamp(uri));
                        return bitmap;
                    }
                } catch (Throwable e) {
                    LogUtils.e(e.getMessage(), e);
                } finally {
                    IOUtils.closeQuietly(snapshot);
                }
            }
            return null;
        }
    }
 

    public void clearDiskCache() {
        synchronized (mDiskCacheLock) {
            if (mDiskLruCache != null && !mDiskLruCache.isClosed()) {
                try {
                    mDiskLruCache.delete();
                } catch (Throwable e) {
                    LogUtils.e(e.getMessage(), e);
                }
                mDiskLruCache = null;
                isDiskCacheReadied = false;
            }
        }
        initDiskCache();
    }
 

    public void clearDiskCache(String uri) {
        synchronized (mDiskCacheLock) {
            if (mDiskLruCache != null && !mDiskLruCache.isClosed()) {
                try {
                    mDiskLruCache.remove(uri);
                } catch (Throwable e) {
                    LogUtils.e(e.getMessage(), e);
                }
            }
        }
    }

    /**
     * Flushes the disk cache associated with this ImageCache object. Note that this includes
     * disk access so this should not be executed on the main/UI thread.
     */
    public void flush() {
        synchronized (mDiskCacheLock) {
            if (mDiskLruCache != null) {
                try {
                    mDiskLruCache.flush();
                } catch (Throwable e) {
                    LogUtils.e(e.getMessage(), e);
                }
            }
        }
    }

    /**
     * Closes the disk cache associated with this ImageCache object. Note that this includes
     * disk access so this should not be executed on the main/UI thread.
     */
    public void close() {
        synchronized (mDiskCacheLock) {
            if (mDiskLruCache != null) {
                try {
                    if (!mDiskLruCache.isClosed()) {
                        mDiskLruCache.close();
                        mDiskLruCache = null;
                    }
                } catch (Throwable e) {
                    LogUtils.e(e.getMessage(), e);
                }
            }
        }
    }

    private class BitmapMeta {
        public FileInputStream inputStream;
        public byte[] data;
        public long expiryTimestamp;
    }

    

    public class MemoryCacheKey {
        private String uri;
        private String subKey;

        private MemoryCacheKey(String uri, String subKey) {
            this.uri = uri;
            this.subKey = subKey;
        }

      
    }
}

프로젝트 에서 다운로드 모듈 을 만 들 때 도 스 레 드 상황 이 발생 합 니 다.다운로드 한 파일 지원 시작,일시 정지,계속,정지점 전송 등 기능 을 사용 합 니 다.그 당시 일시 정지(계속)를 할 때 다운로드 대상 의 변수 값 을 사용 하여 판단 한 다음 에 스 레 드 의 sleep 을 사용 하여 일시 정지 기능 을 실현 합 니 다.
HttpURLConnection mConnection = null;
        URL url = null;
        InputStream inputStream = null;
        RandomAccessFile outputStream = null;
        mModel = params[0];
        try {
//        	url = new URL("https://download.gamm.ztgame.com/apk/lutachuanqi.apk");
        	url = new URL(mModel.getmDownloadUrl());
            mConnection = (HttpURLConnection) url.openConnection();
         
            mConnection.setDoInput(true);
            mConnection.setAllowUserInteraction(true);
            mConnection.setRequestMethod("GET");
            mConnection.setReadTimeout(60000);//
            mConnection.setRequestProperty("User-Agent", "NetFox");
            mConnection.setRequestProperty("Accept-Encoding","identity");
            mConnection.setRequestProperty("Range","bytes=" + mModel.getmDownloadPosition() + "-");
            mConnection.setRequestProperty("Connection","Keep-Alive");//
            mConnection.connect();
            mStateCode = mConnection.getResponseCode();

            inputStream = mConnection.getInputStream();
            length = mConnection.getContentLength() + mModel.getmDownloadPosition();


            File outFile = new File(Environment.getExternalStorageDirectory()
                    .getPath() + PluginDownloadUtil.DOWN_DIR, mModel.getmDownloadName()+".apk");
            if (!outFile.exists()) {
                try {
                    outFile.getParentFile().mkdir();
                    outFile.createNewFile();
                } catch (IOException e) {

                    e.printStackTrace();
                }
            }
            //
            try {
                outputStream = new RandomAccessFile(outFile, "rwd");
            } catch (FileNotFoundException e) {

                e.printStackTrace();
            }
            //
            outputStream.seek(mModel.getmDownloadPosition());
            byte[] buf = new byte[1024 * 100];
            int read = 0;
            curSize = mModel.getmDownloadPosition();

            //Log.e("--------Task-----------", "-------downstatus----------------" + mModel.getmDownloadName() + ",length = " + mConnection.getContentLength());
            if (mConnection.getContentLength() != -1){
                mModel.getmDatabase().updateInfoById(mModel.getmDownloadId(),
                        DownloadDB.COLUMN_DOWNLOAD_PKG_SIZE, mConnection.getContentLength());


                while (mModel.getmDownloadStatues() < 4
                        && mModel.getmDownloadStatues() > 0) {
                    while ((mModel.getmDownloadStatues() == 2)||(mModel.getmDownloadStatues() == 3)) {
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    read = inputStream.read(buf);
                    if (read == -1 || mModel.getmDownloadStatues() == 0) {

                        break;
                    }
                    outputStream.write(buf, 0, read);
                    curSize = curSize + read;
                    int progress = (int) ((curSize * 100) / length);
                    publishProgress(progress);
                    mModel.setmDownloadPosition((int) curSize);
                    mModel.getmDatabase().updateInfoById(mModel.getmDownloadId(),
                            DownloadDB.COLUMN_DOWNLOAD_POSITION, (int) curSize);
                    mModel.setmDownloadProgress(progress);
                    mModel.getmDatabase().updateInfoById(mModel.getmDownloadId(),
                            DownloadDB.COLUMN_DOWNLOAD_PROGRESS, progress);

                    if (curSize == length) {
                        Message msg = mUpdateUiHandler.obtainMessage();
                        msg.what = 1;
                        mUpdateUiHandler.sendMessage(msg);
                        mModel.setmDownloadStatues(4);
                        mModel.getmDatabase().updateInfoById(mModel.getmDownloadId(), DownloadDB.COLUMN_DOWNLOAD_STATUES, 4);

                        break;
                    }
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                return "success";
            }else {
                if (mStateCode == 416||mStateCode == 206){
                    mModel.setmDownloadStatues(0);
                    mModel.setmDownloadPosition(0);
                    mModel.setmDownloadProgress(0);

                    mModel.getmDatabase().updateInfoBeanId(mModel.getmDownloadId());
                }

                return "exception";
            }

        } catch (IOException e) {
            e.printStackTrace();
            if (mStateCode == 416||mStateCode == 206){
                mModel.setmDownloadStatues(0);
                mModel.setmDownloadPosition(0);
                mModel.setmDownloadProgress(0);
                mModel.getmDatabase().updateInfoBeanId(mModel.getmDownloadId());
            } else {
                mModel.setmDownloadStatues(0);
                mModel.getmDatabase().updateInfoById(mModel.getmDownloadId(), "download_statues", 0);
            }

            return "exception";
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (mConnection != null) {
            	mConnection.disconnect();
            }

        }

좋은 웹페이지 즐겨찾기