fix: thread.interrupt() not quit looper

This commit is contained in:
hyb1996
2018-03-15 16:35:22 +08:00
parent 40f7941064
commit 0d94c36d8c
5 changed files with 20 additions and 19 deletions

View File

@@ -3,6 +3,7 @@ package com.stardust.autojs.core.looper;
import android.os.Handler;
import android.os.Looper;
import android.os.MessageQueue;
import android.util.Log;
import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.autojs.runtime.api.Threads;
@@ -18,6 +19,8 @@ import java.util.concurrent.CopyOnWriteArrayList;
public class Loopers implements MessageQueue.IdleHandler {
private static final String LOG_TAG = "Loopers";
public interface LooperQuitHandler {
boolean shouldQuit();
}
@@ -139,11 +142,14 @@ public class Loopers implements MessageQueue.IdleHandler {
if (l == null)
return true;
if (l == mMainLooper) {
Log.d(LOG_TAG, "main looper queueIdle");
if (shouldQuitLooper() && !mThreads.hasRunningThreads() &&
mMainLooperQuitHandler != null && mMainLooperQuitHandler.shouldQuit()) {
Log.d(LOG_TAG, "main looper quit");
l.quit();
}
} else {
Log.d(LOG_TAG, "looper queueIdle: " + l);
if (shouldQuitLooper()) {
l.quit();
}
@@ -153,12 +159,13 @@ public class Loopers implements MessageQueue.IdleHandler {
public void prepare() {
if (Looper.myLooper() == null)
Looper.prepare();
LooperHelper.prepare();
Looper.myQueue().addIdleHandler(this);
waitWhenIdle.set(Looper.myLooper() == Looper.getMainLooper());
}
public void notifyThreadExit(TimerThread thread) {
Log.d(LOG_TAG, "notifyThreadExit: " + thread);
//当子线程退成时,主线程需要检查自身是否退出(主线程在所有子线程执行完成后才能退出,如果主线程已经执行完任务仍然要等待所有子线程),
//此时通过向主线程发送一个空的Runnable主线程执行完这个Runnable后会触发IdleHandler从而检查自身是否退出
mMainHandler.post(EMPTY_RUNNABLE);

View File

@@ -57,6 +57,12 @@ public class TimerThread extends ThreadCompat {
}
}
@Override
public void interrupt() {
LooperHelper.quitForThread(this);
super.interrupt();
}
private void notifyRunning() {
synchronized (mRunningLock) {
mRunning = true;

View File

@@ -6,21 +6,9 @@ import com.stardust.autojs.core.looper.MainThreadProxy;
import com.stardust.autojs.core.looper.TimerThread;
import com.stardust.autojs.engine.RhinoJavaScriptEngine;
import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.concurrent.VolatileBox;
import com.stardust.concurrent.VolatileDispose;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@@ -55,7 +43,7 @@ public class Threads {
}
public TimerThread start(Runnable runnable) {
TimerThread thread = startThread(runnable);
TimerThread thread = createThread(runnable);
synchronized (mThreads) {
mThreads.add(thread);
thread.setName(thread.getName() + " (Spawn-" + mSpawnCount + ")");
@@ -66,7 +54,7 @@ public class Threads {
}
@NonNull
private TimerThread startThread(Runnable runnable) {
private TimerThread createThread(Runnable runnable) {
return new TimerThread(mRuntime, mRuntime.timers.getMaxCallbackUptimeMillisForAllThreads(),
() -> {
((RhinoJavaScriptEngine) mRuntime.engines.myEngine()).createContext();

View File

@@ -80,9 +80,9 @@ public class Timers {
public boolean hasPendingCallbacks() {
//如果是脚本主线程则检查所有子线程中的定时回调。mFutureCallbackUptimeMillis用来记录所有子线程中定时最久的一个。
if (mThreads.getMainThread() == Thread.currentThread()) {
return mMaxCallbackUptimeMillisForAllThreads.get() > SystemClock.uptimeMillis();
}
// if (mThreads.getMainThread() == Thread.currentThread()) {
// return mMaxCallbackUptimeMillisForAllThreads.get() > SystemClock.uptimeMillis();
//}
//否则检查当前线程的定时回调
return getTimerForCurrentThread().hasPendingCallbacks();
}