转自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
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
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----------
……
}
}
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;
}
}
}
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();
}
}