Skip to content

Instantly share code, notes, and snippets.

@vovkab
Created March 8, 2018 05:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vovkab/1f955a8c0fda3f5ca7af7071ef105a08 to your computer and use it in GitHub Desktop.
Save vovkab/1f955a8c0fda3f5ca7af7071ef105a08 to your computer and use it in GitHub Desktop.
Monitors main thread for timeouts.
package io.wondrous.sns.utils;
import android.os.Handler;
import android.os.Looper;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
public class MainThreadWatchDog {
public static final long MAIN_THREAD_PING_INTERVAL = 200;
public static final long MAIN_THREAD_TIMEOUT = 500;
private final Handler mHandler;
private final AtomicLong mTimestamp = new AtomicLong();
private final AtomicBoolean mIsStopped = new AtomicBoolean();
public MainThreadWatchDog(Handler handler) {
mHandler = handler;
}
public void start() {
mHandler.post(mMainThreadRunnable);
mThread.start();
}
public void stop() {
mIsStopped.set(true);
}
private final Runnable mMainThreadRunnable = new Runnable() {
@Override
public void run() {
mTimestamp.set(System.currentTimeMillis());
mHandler.postDelayed(this, MAIN_THREAD_PING_INTERVAL);
}
};
private final Thread mThread = new Thread(new Runnable() {
@Override
public void run() {
while (!mIsStopped.get()) {
try {
final long timestamp = mTimestamp.get();
final long timeDiff = System.currentTimeMillis() - timestamp;
if (timestamp > 0 && timeDiff > MAIN_THREAD_TIMEOUT) {
StringBuilder sb = new StringBuilder();
sb.append("Main thread timeout (").append(timeDiff).append("ms):\n");
StackTraceElement[] stackTrace = Looper.getMainLooper().getThread().getStackTrace();
sb.append(printStackTrace(stackTrace));
throw new RuntimeException(sb.toString());
}
Thread.sleep(MAIN_THREAD_TIMEOUT);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
private String printStackTrace(StackTraceElement[] stackTrace) {
StringBuilder sb = new StringBuilder();
for (int i = 1; i < stackTrace.length; i++) {
StackTraceElement s = stackTrace[i];
sb.append("\tat " + s.getClassName() + "." + s.getMethodName()
+ "(" + s.getFileName() + ":" + s.getLineNumber() + ")\n");
}
return sb.toString();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment