HandlerThread source code analysis
How do I use 1?
Now suppose you have a scenario that requires you to run a time-consuming operation in a child thread. How? A subthread must have a Handler in it:
Public class MThread extends Thread {public class MThread extends Thread {private MThread extends Thread; @Override public void run() { Looper.prepare(); // Create Looper Handler = new handler (); Looper looper.loop (); Looper looper.loop (); Public Handler getHandler() {return Handler; }}Copy the code
With the child threads created, we started using them
MThread mThread = new MThread(); // Create the thread mthread.start (); Mthread.gethandler ().sendMessage(new Message()); // Get this thread's Handler and send concurrent messagesCopy the code
If mthread.gethandler () is null, then mthread.gethandler () is null. If mthread.start () is null, then mthread.run () is null. Handler = new handler (); HandlerThread = new handler ();
2 Source code Analysis
public class HandlerThread extends Thread { int mPriority; int mTid = -1; Looper mLooper; // Provide a Looper private @nullable Handler mHandler for the current thread; Public HandlerThread(String name) {super(name); mPriority = Process.THREAD_PRIORITY_DEFAULT; } public HandlerThread(String name, int priority) { super(name); mPriority = priority; } // This is called after Looper is created, Looper protected void onLooperPrepared() {} @override public void run() {mTid = process.mytid (); Looper.prepare(); // synchronized () {mLooper = looper.mylooper (); // assign notifyAll() to mLooper; / / wake up the other waiting for "this" lock the thread} Process. The setThreadPriority (mPriority); onLooperPrepared(); / / callback stars. The loop (); MTid = -1; } public Looper getLooper() {if (! IsAlive ()) {// if the current thread no longer exists, return null; } synchronized (this) {// synchronized (this) {while (isAlive() && mLooper == null) {// if the thread is still alive and mLooper is null, Try {wait(); // Wait for the notifyAll() in run()} catch (InterruptedException e) {}} return mLooper; // Wait for the notifyAll() in run()} catch (InterruptedException e) {}} return mLooper; Public Handler getThreadHandler() {if (mHandler == null) {mHandler = new Handler(getLooper()); // getLooper() is also called, so if mLooper hasn't been created yet, it will be stuck here} return mHandler; Public Boolean quit() {Looper Looper = getLooper(); if (looper ! = null) { looper.quit(); return true; } return false; } // Exit safely from MessageQueue and delete only messages that are not to be executed until the end of the message. For example, if quitSafely is called at the end of A, MessageQueue for MSG. When >=A will be retrieved. Public Boolean quitSafely() {Looper Looper = getLooper(); if (looper ! = null) { looper.quitSafely(); return true; } return false; } public int getThreadId() { return mTid; }}Copy the code
From the above code we know:
- 1 HandlerThread is a Thread that contains a Handler and a Looper
- 2. Create Looper in run(), add synchronization lock, lock object is itself
- GetLooper () ¶ getLooper() ¶ getLooper() ¶ getLooper() ¶
- 4 Go to getLooper() inside getHandler() to create the Handler
- 5 So if Looper has not been assigned, the current thread will wait() until the synchronized blocks in MThread’s run have run, then return and continue execution
Q: What if getLooper() is in mthread.start () first? Does it deadlock? Such as:
MThread thread = new MThread(); thread.getLooper(); // Synchronized (this) and wait() for notify thread.start(); // Synchronized in run() cannot enter and is stuck waiting for this lock, thus creating a deadlockCopy the code
A: No, because when thread.getlooper () does not start(), then isAlive() is false and it immediately returns null, so it does not.
Q: But threads are uncertain. If I start() the thread, wait until it runs to synchronized(this) in run(), and then immediately go to thread.getlooper (), If (isAlive()) is skipped, but what if synchronized() in getLooper() gets this first? The process is as follows:
public void run() { mTid = Process.myTid(); Looper.prepare(); // synchronized (1) {mLooper = looper.mylooper (); // synchronized (1) {mLooper = Looper. // assign notifyAll() to mLooper; / / wake up the other waiting for "this" lock the thread} Process. The setThreadPriority (mPriority); onLooperPrepared(); / / callback stars. The loop (); MTid = -1; } public Looper getLooper() {if (! IsAlive ()) {//(2 runs here) return null; } synchronized (this) {//(synchronized) while (isAlive() && mLooper == null) {//(synchronized) try {wait(); (6) } catch (InterruptedException e) { } } } return mLooper; }Copy the code
A: No, because the above code also has a (6). What does the 6 do? Wait, yes, but in addition to waiting, wait() also releases the lock!! If wait(), then run() will continue, so there is no deadlock. A deadlock can only occur if there are more than two locks!!