Android 스 레 드 의 끝,끊 기 및 복구
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();
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.