记录一下开发中遇到的这些东西,讲解的不多,毕竟这些都是陈芝麻烂谷子的东西了,就是把源码堆在这里加了一些注释.
如果每个线程都想有自己的共享变量就得使用ThreadLocal,这个类解决了每个线程绑定自己的值,可以将这个类比喻成为全局存放数据的盒子,盒子中可以存储每个线程的私有数据.保证每个线程变量的隔离性.
public final class Looper {
private static final String TAG = "Looper";
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static Looper sMainLooper; // guarded by Looper.class
final MessageQueue mQueue;
final Thread mThread;
private Printer mLogging;
private long mTraceTag;
private long mSlowDispatchThresholdMs;
private long mSlowDeliveryThresholdMs;
//无参构造,默认调用true,表示Looper允许退出
public static void prepare() {
prepare(true);
}
//这个方法在每个线程只允许执行一次,它会创建Looper对象,将Looper对象保存到当前线程TLS。
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
public static Looper getMainLooper() {
synchronized (Looper.class) {
return sMainLooper;
}
}
public static void loop() {
//获取Looper对象
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
//获取消息
final MessageQueue queue = me.mQueue;
////确保此线程的标识是本地进程的标识,并标记。
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
// Allow overriding a threshold with a system prop. e.g.
// adb shell 'setprop log.looper.1000.main.slow 1 && stop && start'
final int thresholdOverride =
SystemProperties.getInt("log.looper."
+ Process.myUid() + "."
+ Thread.currentThread().getName()
+ ".slow", 0);
boolean slowDeliveryDetected = false;
//开始循环
for (;;) {
Message msg = queue.next(); // 可能会阻塞
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
final long traceTag = me.mTraceTag;
long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
long slowDeliveryThresholdMs = me.mSlowDeliveryThresholdMs;
if (thresholdOverride > 0) {
slowDispatchThresholdMs = thresholdOverride;
slowDeliveryThresholdMs = thresholdOverride;
}
final boolean logSlowDelivery = (slowDeliveryThresholdMs > 0) && (msg.when > 0);
final boolean logSlowDispatch = (slowDispatchThresholdMs > 0);
final boolean needStartTime = logSlowDelivery || logSlowDispatch;
final boolean needEndTime = logSlowDispatch;
if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
}
final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
final long dispatchEnd;
try {
//用于分发消息
msg.target.dispatchMessage(msg);
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
if (logSlowDelivery) {
if (slowDeliveryDetected) {
if ((dispatchStart - msg.when) <= 10) {
Slog.w(TAG, "Drained");
slowDeliveryDetected = false;
}
} else {
if (showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart, "delivery",
msg)) {
// Once we write a slow delivery log, suppress until the queue drains.
slowDeliveryDetected = true;
}
}
}
if (logSlowDispatch) {
showSlowLog(slowDispatchThresholdMs, dispatchStart, dispatchEnd, "dispatch", msg);
}
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
//回收消息
msg.recycleUnchecked();
}
}
//返回与当前线程关联的Looper对象。 如果调用线程未与Looper关联,则返回null。
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
//返回与当前线程关联的{@link MessageQueue}对象。 而且必须从运行中的Looper线程调用它,否则将抛出NullPointerException。
public static @NonNull MessageQueue myQueue() {
return myLooper().mQueue;
}
//这里创建了MessageQueue对象,而且获取了前正在执行的线程对象的引用。
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
//如果当前线程是Looper线程,则返回true。
public boolean isCurrentThread() {
return Thread.currentThread() == mThread;
}
public void setMessageLogging(@Nullable Printer printer) {
mLogging = printer;
}
/** {@hide} */
public void setTraceTag(long traceTag) {
mTraceTag = traceTag;
}
/**
* Set a thresholds for slow dispatch/delivery log.
* {@hide}
*/
public void setSlowLogThresholdMs(long slowDispatchThresholdMs, long slowDeliveryThresholdMs) {
mSlowDispatchThresholdMs = slowDispatchThresholdMs;
mSlowDeliveryThresholdMs = slowDeliveryThresholdMs;
}
//把消息移除,直接移除所以的消息
public void quit() {
mQueue.quit(false);
}
//安全的将消息移除,只移除没有触发的所有消息,对于正在触发的消息不移除;
public void quitSafely() {
mQueue.quit(true);
}
public @NonNull Thread getThread() {
return mThread;
}
public @NonNull MessageQueue getQueue() {
return mQueue;
}
}
Android给出一个小例子,为什么要这样做就清楚了:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
在主线程的MessageQueue没有消息时,便阻塞在loop的 queue.next()
中的nativePollOnce()方法里,此时主线程会释放CPU资源进入休眠状态,直到下个消息到达或者有事务发生,通过往pipe管道写端写入数据来唤醒主线程工作。这里采用的epoll机制,是一种IO多路复用机制,可以同时监控多个描述符,当某个描述符就绪(读或写就绪),则立刻通知相应程序进行读或写操作,本质同步I/O,即读写是阻塞的。
所以说,主线程大多数时候都是处于休眠状态,并不会消耗大量CPU资源。(引用Gityuan的原话)
public class Handler {
public interface Callback {
public boolean handleMessage(Message msg);
}
public void handleMessage(Message msg) {
}
//分发消息
public void dispatchMessage(Message msg) {
//当Message存在回调方法,回调msg.callback.run()方法;
if (msg.callback != null) {
handleCallback(msg);
} else {
//当Handler存在Callback成员变量时,回调方法handleMessage();
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
//或者覆写了这个方法那就回调这个
handleMessage(msg);
}
}
//调用默认构造函数将与当前线程里面的Looper关联
// 如果此线程没有looper,则此处理程序将无法接收消息,因此会引发异常。
public Handler() {
this(null, false);
}
//可以设置回调接口Callback
public Handler(Callback callback) {
this(callback, false);
}
//可以设置Looper
public Handler(Looper looper) {
this(looper, null, false);
}
public Handler(Looper looper, Callback callback) {
this(looper, callback, false);
}
public Handler(boolean async) {
this(null, async);
}
public Handler(Callback callback, boolean async) {
//静态警告
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
//获取当前线程的Looper
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
//获取队列
mQueue = mLooper.mQueue;
//回调
mCallback = callback;
//设置消息的同步或异步
mAsynchronous = async;
}
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
//发送消息
public final boolean sendEmptyMessage(int what) {
return sendEmptyMessageDelayed(what, 0);
}
......
//所有的消息最终都是调用这个方法
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
//把消息放入队列中处理
return queue.enqueueMessage(msg, uptimeMillis);
}
}
MessageQueue很复杂这里就不说了.
但是我们要知道MessageQueue是按照Message触发时间的先后顺序排列的,队头的消息是将要最早触发的消息。当有消息需要加入消息队列时,会从队列头开始遍历,直到找到消息应该插入的合适位置,以保证所有消息的时间顺序。(引用Gityuan的原话)
MessageQueue的主要方法 next();enqueueMessage(); 处理了消息的取出与加入
// 创建HandlerThread线程包含Looper
HandlerThread handlerThread = new HandlerThread("gityuan.com");
handlerThread.start();
// 创建Handler
Handler handler = new Handler(handlerThread.getLooper());
// 发送消息
handler.post(new Runnable() {
@Override
public void run() {
System.out.println("to do something");
});
//////////////////////源码//////////////////////////////////////////////////////
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
private @Nullable Handler mHandler;
public HandlerThread(String name) {
super(name);
//默认进程等级
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
protected void onLooperPrepared() {
}
@Override
public void run() {
//tid
mTid = Process.myTid();
//new 一个Looper
Looper.prepare();
synchronized (this) {
//获取Looper
mLooper = Looper.myLooper();
//唤醒等待的全部线程
notifyAll();
}
Process.setThreadPriority(mPriority);
//循环之前做点什么,空方法,可以覆写
onLooperPrepared();
//循环
Looper.loop();
mTid = -1;
}
//获取Looper
public Looper getLooper() {
//线程没有启动,返回null
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.等待Looper不为null
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
@NonNull
public Handler getThreadHandler() {
if (mHandler == null) {
mHandler = new Handler(getLooper());
}
return mHandler;
}
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}
public int getThreadId() {
return mTid;
}
}
这样就可以实现线程间的通信了.
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
private String mName;
private boolean mRedelivery;
//消息回调
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
//调用onHandleIntent
onHandleIntent((Intent)msg.obj);
//最终调用mActivityManager.stopServiceToken
stopSelf(msg.arg1);
}
}
/**
* 创建一个IntentService。 由子类的构造函数调用。
*
* @param name Used to name the worker thread, important only for debugging.
*/
public IntentService(String name) {
super();
mName = name;
}
/**
* 重新传递intent参数选项
*/
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
@Override
public void onCreate() {
super.onCreate();
//创建HandlerThread
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
//获取Looper
mServiceLooper = thread.getLooper();
//创建Handler
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
//处理收到的intent任务
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
/**
*您不应该为IntentService重写此方法。我们需要重写的onHandleIntent,这个方法是系统在IntentService收到启动请求时调用。
*/
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onDestroy() {
//移除任务
mServiceLooper.quit();
}
@Override
@Nullable
public IBinder onBind(Intent intent) {
return null;
}
//工作线程,耗时操作在这里面执行,一次只能处理一个Intent,处理完所有请求后,IntentService会自行停止.
//所以最好不要调用stopService,即使你调用了服务停止了.任务也会继续执行完.
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
}
START_NOT_STICKY
如果onStartCommand() 执行完毕后,系统意外关闭服务,系统不会重启服务。
START_STICKY
如果onStartCommand() 执行完毕后,系统意外关闭服务,会重新创建服务并调用onStartCommand() 方法,但是不会重新发送intent,而是给onStartCommand() 一个null的intent。
START_REDELIVER_INTENT
如果onStartCommand() 执行完毕后,系统意外关闭服务,会重新创建服务并调用onStartCommand() 方法,但是不会重新发送intent,而是给onStartCommand() 一个最后发送的intent。
最后通过源码我们发现IntentService不可以直接和UI做交互,工作任务队列是顺序执行的,如果一个任务正在IntentService中执行,此时你再发送一个新的任务请求,这个新的任务会一直等待直到前面一个任务执行完毕才开始执行,而且正在执行的任务无法打断。