Android thread analysis and supplement
I. Two questions about Logoff
1) Question 1: logoff. loop () is to process messages, all messages or part of messages?
2) Question 2: After the message is processed, the message ends or waits?
Android official sample document code:
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(); } }
Look at the logoff source code and you will know:
public class Looper {
public static void prepare() {
... // Initialize the Message Queue
}
public static void loop() {
MessageQueue queue = me.mQueue;
while (true) {
Message msg = queue.next(); // might block
if (msg != null) {
if (msg.target == null) {
return;
}
// Process this message
msg.target.dispatchMessage(msg);
}
}
}
public void quit() {
Message msg = Message.obtain();
// Send a message. The message content is empty.
mQueue.enqueueMessage(msg, 0);
// Loop () ends itself when an empty message is processed.
}
}
Source code analysis:
1) logoff. prepare () is to initialize the message queue.
2) logoff. loop () is used to process all messages.
While (true) is an endless loop that processes all messages cyclically. After processing all the messages, it is still an endless loop, waiting for the arrival of new messages.
The only condition for unlocking is that a message is retrieved from the queue and the message target is empty.
3) logoff. quit () is to construct a message with empty content and put it into the queue. The essence is to end processing the message.
Ii. Handling of GLSurfaceView queue events
Question 1: Does GLSurfaceView process all or some messages in one frame?
Question 2: Does the event queue affect the frame rate?
Look at the source code of GLSurfaceView:
public class GLSurfaceView extends SurfaceView
implements SurfaceHolder.Callback {
// Insert event queue
public void queueEvent(Runnable r) {
mGLThread.queueEvent(r);
}
// Loop logic in the thread
private void guardedRun(){
While (true) {// The loop of onDrawFrame
While (true) {// message processing cycle
if (! mEventQueue.isEmpty()) {
event = mEventQueue.remove(0);
break;
}
…
if (event != null) {
event.run();
event = null;
continue;
}
} // End message processing cycle
…
mRenderer.onDrawFrame(gl);
}
}
// Internal class, thread
class GLThread extends Thread {
GLThread(Renderer renderer) {
}
@Override
public void run() {
guardedRun();
}
public void queueEvent(Runnable r) {
mEventQueue.add(r);
}
}
}
Source code analysis:
1) All messages are processed at one time.
2) as long as a message exists in the queue, onDrawFrame () cannot be executed. Therefore, message queues have a great impact on the frame rate. The priority of any new message is higher than that of onDrawFrame.
3. wait () and Policy () in the Java thread ()
Problem: Sometimes, threads wait for each other. Is there a good solution? Wait ()?
Conclusion: The wait () method can be called only in the synchronous method or block. Therefore, a reasonable scheduling logic must be compiled for reasonable thread scheduling to avoid the issue of waiting between threads (refer to the producer-consumer mode ).
We will not change the existing thread logic of 801 for the moment. Because the business is complex, it is inconvenient to schedule another object. Locking also reduces efficiency.
The following describes the classic producer-consumer model:
Clerk. java:
package onlyfun.caterpillar;
public class Clerk {
//-1 indicates that no product exists.
private int product = -1;
// This method is called by the producer
public synchronized void setProduct(int product) {
if(this.product != -1) {
try {
// Currently, the clerk has no space to accept the product. Please wait!
wait();
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
this.product = product;
System. out. printf ("producer settings (% d) % n", this. product );
// Notification that a consumer in the waiting area can continue to work.
notify();
}
// This method is called by the consumer
public synchronized int getProduct() {
if(this.product == -1) {
try {
// Out of stock. Please wait!
wait();
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
int p = this.product;
System. out. printf ("the consumer removes (% d) % n", this. product );
This. product =-1; // remove the product.-1 indicates that the current clerk has no products.
// Notify a producer in the waiting area to continue working.
notify();
return p;
}
}
Producer. java:
package onlyfun.caterpillar;
public class Producer implements Runnable {
private Clerk clerk;
public Producer(Clerk clerk) {
this.clerk = clerk;
}
public void run() {
System. out. println ("the producer starts to produce integers ......");
// Produce an integer ranging from 1 to 10
for(int product = 1; product <= 10; product++) {
try {
// Pause the random time
Thread.sleep((int) Math.random() * 3000);
}
catch(InterruptedException e) {
e.printStackTrace();
}
// Deliver the product to the clerk
clerk.setProduct(product);
}
}
}
Consumer. java:
package onlyfun.caterpillar;
public class Consumer implements Runnable {
private Clerk clerk;
public Consumer(Clerk clerk) {
this.clerk = clerk;
}
public void run() {
System. out. println ("the consumer begins to consume an integer ......");
// Consumes 10 Integers
for(int i = 1; i <= 10; i++) {
try {
// Wait for the random time
Thread.sleep((int) (Math.random() * 3000));
}
catch(InterruptedException e) {
e.printStackTrace();
}
// Remove the integer from the clerk
clerk.getProduct();
}
}
}