public class LooperExecutor extends Thread implements Executor {
private static final String TAG = "LooperExecutor";
// Object used to signal that looper thread has started and Handler instance
// associated with looper thread has been allocated.
private final Object looperStartedEvent = new Object();
private final List<Runnable> scheduledPeriodicRunnables = new LinkedList<Runnable>();
private Handler handler = null;
private boolean running = false;
private long threadId;
@Override
public void run() {
Looper.prepare();//为该线程准备好Looper对象 并且准备好消息队列
synchronized (looperStartedEvent) {
Log.d(TAG, "Looper thread started.");
handler = new Handler();
threadId = Thread.currentThread().getId();
looperStartedEvent.notify();
}
Looper.loop();
}
public synchronized void requestStart() {
if (running) {
return;
}
running = true;
handler = null;
start();
// Wait for Hander allocation.
synchronized (looperStartedEvent) {
while (handler == null) {
try {
looperStartedEvent.wait();//如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态
//调用任意对象的 wait() 方法导致该线程阻塞,该线程不可继续执行,并且该对象上的锁被释放
} catch (InterruptedException e) {
Log.e(TAG, "Can not start looper thread");
running = false;
}
}
}
}
public synchronized void requestStop() {
if (!running) {
return;
}
running = false;
handler.post(new Runnable() {
@Override
public void run() {
handler.getLooper().quit();
Log.d(TAG, "Looper thread finished.");
}
});
}
// Checks if current thread is a looper thread.
public boolean checkOnLooperThread() {
return (Thread.currentThread().getId() == threadId);
}
public synchronized void scheduleAtFixedRate(final Runnable command, final long periodMillis) {
if (!running) {
Log.w(TAG, "Trying to schedule task for non running executor");
return;
}
Runnable runnable = new Runnable() {
@Override
public void run() {
if (running) {
command.run();
if (!handler.postDelayed(this, periodMillis)) {
Log.e(TAG, "Failed to post a delayed runnable in the chain.");
}
}
}
};
scheduledPeriodicRunnables.add(runnable);
if (!handler.postDelayed(runnable, periodMillis)) {
Log.e(TAG, "Failed to post a delayed runnable.");
}
}
public synchronized void cancelScheduledTasks() {
if (!running) {
Log.w(TAG, "Trying to cancel schedule tasks for non running executor");
return;
}
// Stop scheduled periodic tasks.
for (Runnable r : scheduledPeriodicRunnables) {
handler.removeCallbacks(r);
}
scheduledPeriodicRunnables.clear();
}
@Override
public synchronized void execute(final Runnable runnable) {
if (!running) {
Log.w(TAG, "Running looper executor without calling requestStart()");
return;
}
if (Thread.currentThread().getId() == threadId) {
runnable.run();
} else {
handler.post(runnable);
}
}
/**
* Access to the handler for testing purposes.
*/
Handler getHandler() {
return handler;
}
}