转自http://blog.sina.com.cn/s/blog_4c0706560101175r.html

Android线程类也提供了一些公共方法去挂起和恢复线程:

final void resume()                                       //This method is deprecated. Used with deprecated method suspendfinal void suspend()//This method is deprecated. May cause deadlocks

同样不幸的是,通过说明我们可以看到,这些方法Android也是不推荐使用的,经过笔者试验,这些方法也没有效果
Android的类基本都是继承于Object类。此类可以说是Android类的祖先了。如果把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 wokenfinal void notifyAll()Causes all threads which are waiting on this object's monitor (by means of calling one of the wait() methods) to be wokenfinal void wait()Causes the calling thread to wait until another thread calls the notify() or notifyAll() method of this object

通过说明我们可以知道,wait方法可以让正在调用的线程处于等待状态,直到其他线程调用了该对象的notify 或者notifyAll,而notify 和notifyAll方法则是用于唤醒处于等待中的线程。
       同样,线程类也是继承于Object类,但是线程类是一个比较特殊的类,有自己独立的栈机制来处理其方法,参数和局部变量。通过实验,笔者发现,虽然线程类继承于Object类,但是却不能通过wait和notify方法挂起唤醒线程。而要实现上述动作,必须去间接地实现,即在自定义线程类中创建一个Object对象,然后通过对该Object的相关操作实现线程的挂起和唤醒。方法如下:
1.    在自定义线程类的实例化过程中创建一个Object对象。
2.    定义一个变量来记录线程的状态是否挂起,初始化为假。
3.    在线程类中的run函数中的线程执行部分找入锲点来执行下面动作:如果当前状态变量为假(表示线程挂起),则通过1中Object对象的wait方法挂起当前线程,即线程暂停在锲点位置,如果被唤起,则将从锲点后继续执行。
4.    定义一个方法来修改线程状态变量为真,从而达到挂起线程的目的。
5.    定义一个方法去唤醒线程。判断如果线程状态变量为真,则修改其为假,然后调用1中Object对象的notifyAll方法唤醒对象。(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();            }        }















更多相关文章

  1. Android简单实现启动画面的方法
  2. Android 判断Root的方法
  3. android 获取锁屏,解锁的方法
  4. android中的activity里获得context方法
  5. android paint设置字体 中文字体 楷体 和自动换行方法(zhuan)
  6. Android 子线程更新UI
  7. Android发送短信,并监听短信发送后是否发送成功的实现方法
  8. 找不到R.java 解决方法

随机推荐

  1. 20145328 《Java程序设计》实验四实验报
  2. Android(安卓)高仿抖音双击点赞效果
  3. PermissionsDispatcher动态权限申请
  4. Android加载图片出现内存溢出攻略
  5. Android(安卓)Studio插件Gsonformat使用
  6. Android笔记汇总
  7. Android(安卓)ApiDemos示例解析(55):Grap
  8. Android(安卓)P版本编译出现报错ninja: b
  9. Android(安卓)性能优化的一些方法
  10. android:imeOptions="actionDone"