HandlerThread를 통해 네트워크 요청 성공률(스레드 간 통신) 보장
처음에 생각한 것은 Timer였지만 timer에 버그가 있다는 것을 알아냈다.
TimerTask에서 검사되지 않은 예외가 발생하면 Timer는 예측할 수 없는 행동을 합니다.Timer 스레드는 이상을 포착하지 않기 때문에 TimerTask에서 검사하지 않은 이상은 timer 스레드를 종료합니다.이 경우 Timer는 더 이상 라인 실행을 재개하지 않습니다.전체 Timer가 취소되었다고 잘못 생각했습니다.이 때, 이미 안배되었지만 아직 집행하지 않은 TimerTask는 영원히 집행하지 않을 것이며, 새로운 임무도 스케줄링할 수 없습니다.
그리고 자바에서 제공하는 네 가지 스레드 풀의 new ScheduledThreadPool을 생각해 보세요.
newCachedThreadPool은 캐시 가능한 스레드 탱크를 만듭니다. 만약 스레드 탱크의 길이가 처리 수요를 초과하면 빈 스레드를 유연하게 회수할 수 있고, 회수할 수 없으면 새 스레드를 만듭니다.newFixedThreadPool은 최대 병렬 수를 제어할 수 있는 장거리 스레드 탱크를 만듭니다. 초과된 스레드는 대기열에서 기다립니다.newScheduledThreadPool은 정시 및 주기적인 작업 수행을 지원하는 장거리 스레드 탱크를 만듭니다.newSingleThreadExecutor는 모든 작업이 지정된 순서(FIFO, LIFO, 우선순위)에 따라 실행될 수 있도록 유일한 작업 루트로만 작업을 수행합니다.
newScheduledThreadPool
정시 및 주기적인 작업 수행을 지원하는 장거리 스레드 탱크를 만듭니다.지연 실행 예제 코드는 다음과 같습니다.
// , ,int
// 。 ,
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
scheduledThreadPool.schedule(new Runnable() {
@Override
public void run() {
System.out.println("delay 3 seconds");
}
}, 3, TimeUnit.SECONDS);
// 3
정기적 실행 예제 코드는 다음과 같습니다.
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("delay 1 seconds, and excute every 3 seconds");
}
}, 1, 3, TimeUnit.SECONDS);
// 1 3
Scheduled Executor Service는 Timer보다 안전하고 기능이 강하며 자바 프로젝트에서 반나절 동안 테스트를 했는데 사용할 수 있을 것 같았지만 안드로이드 프로젝트에 도착하자마자 문제가 생겼습니다.요청의 실패 리셋에서 주기task를 실행하면 task가 효력을 잃고 Can't create handler inside thread that has not called Looper를 포착합니다.prepare () 예외
@Override
public void fail(Object result) {
executorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
UpdateBusStatusTime updateBusStatusTime = new UpdateBusStatusTime();
//
GetHttpResultTool tool = new GetHttpResultTool(updateBusStatusTime);
tool.setCallback(new GetHttpResultTool.CallBack() {
@Override
public void success(Object result) {
throw new NullPointerException();
}
@Override
public void fail(Object result) {}
});
tool.setPost(true);
tool.execute();
}
},5,5,TimeUnit.SECONDS);
}
okhttp의 접근 요청을 제거하면 모든 것이 정상입니다. okhttp의 냄비일 것입니다. 계속 바꿀 수 없습니다. 결국 HandlerThread를 찾았습니다.
HandlerThread
HandlerThread는 Thread에서 상속되기 때문에 본질은 Thread입니다.일반thread와의 차이점은 하나의 라인을 구축했을 뿐만 아니라 메시지 대기열을 창설했다. 자신의 looper가 있기 때문에 우리는 자신의 라인에서 메시지를 나누어 주고 처리하며 이 Looper 대상의 get 방법을 대외적으로 제공할 수 있다.HandlerThread는 Looper를 가지고 있어서 메시지 대기열을 통해 현재 라인을 반복해서 사용할 수 있습니다.소모 작업이 이 순환 라인에 투입되었을 때, 라인은 소모 작업을 실행하고, 실행이 끝난 후에 순환 라인은 다음 새로운 소모 작업이 투입될 때까지 대기 상태에 있습니다.이렇게 하면 Thread 라인을 여러 번 만들어서 발생하는 성능 문제를 피할 수 있다.이것은 그의 장점이자 단점이다. 모든 임무는 대열의 방식으로 하나하나 실행될 것이다. 일단 대열에 어떤 임무가 너무 오래 실행되면 후속 임무가 지연되어 처리될 것이다.
HandlerThread의 일반적인 사용 방법
1. onCreate 메서드에서 초기화
protected void onCreate(Bundle savedInstanceState) {
// HandlerThread
mCheckMsgThread= new HandlerThread("handler_thread");
// HandlerThread
mCheckMsgThread.start();
// Handler
mCheckMsgHandler = new Handler(mCheckMsgThread.getLooper(), mSubCallback);
// 1
mCheckMsgHandler.sendEmptyMessageDelayed(1, 60 * 1000);
}
2. 순환 메시지 처리 메커니즘 구축
private Handler.Callback mSubCallback = new Handler.Callback() {
// ,
@Override
public boolean handleMessage(Message msg) {
checkForUpdate();
// 5
mCheckMsgHandler.sendEmptyMessageDelayed(1, 5 * 60 * 1000);
return false;
}
};
/**
*
*/
private void checkForUpdate() {
if (errorQueueMap != null && errorQueueMap.size() > 0) {
for (final Map.Entry entry : errorQueueMap.entrySet()) {
if (!entry.getValue()) {
//
final GetHttpResultTool tool = new GetHttpResultTool(entry.getKey());
tool.setCallback(new GetHttpResultTool.CallBack() {
@Override
public void success(final Object result) {
Log.i("", " , " + result);
entry.setValue(true);
// ,
mUIHandler .sendEmptyMessage(2) ;
}
@Override
public void fail(Object result) {
Log.i("", " , " + result);
}
});
}
}
}
}
3. UI 스레드 구축 Handler 처리 메시지
private Handler mUIHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
// handler , UI ,
}
};
4. 순환 Looper를 종료하는 것은 loop 방법을 호출하여 메시지 순환을 구동하는 것입니다. MessageQueue에서 메시지를 막힘없이 꺼내서 Handler로 하여금 이 메시지를 처리하게 하고 반복합니다. loop 방법은 사순환 방법입니다.따라서 onDestroy에서 리소스 방출을 종료해야 합니다.
mCheckMsgThread.quit() ;
원생 스레드 간 통신
간단히 말하자면, Handler를 버리고 원생 자바에서도 사실 라인 간 통신을 할 수 있는 방법이 있다.다만 방법이 우아하지 않거나 cpu 연산 부하가 너무 높거나 자물쇠가 끊어지는 상황을 초래할 수 있다.그리고 기술이 제대로 되지 않아 전복되는 경우가 많다.그래서 android 중의 Hander 통신 메커니즘은 이런 문제를 교묘하게 피하고 원생 방법을 참고하여 학습하도록 제공한다.
총결산
참고http://www.cnblogs.com/wufeng0927/p/5374191.html http://www.jianshu.com/p/69c826c8a87d http://blog.csdn.net/m0_37837382/article/details/70143224
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.