preface

On a sunny afternoon in winter, I rode my beloved yellow bike to an interview. Before the interview many times think, the next interviewer is what kind of.

When I arrived at the company where the interview took place, I simply filled in a piece of personal information at the reception desk. In the information, I had to fill in my ID number, parents’ names and phone numbers. I thought that such sensitive and perfect information would be cheated if it was leaked out, so I thought my parents were likely to be cheated. (I don’t recommend this either.) I was in the interview reception room, and shortly after, the interviewer came by, pen in hand. The interviewer gave me the test. I vaguely remembered that there was a binary search algorithm problem, an understanding of the interruption mechanism of the operating system, and asked me to write a simplified version of the Handle by imitating The Android Handle, but I could not remember the rest.

I use the tone of discussion to ask: this can not handwritten?

The interviewer is a little dismissive: You don’t want to write, do you?

And then he got up, and before I knew it, he turned off the lights in the interview room, and I didn’t know what to do. He also took my water, because I wouldn’t even drink it if I didn’t write the interview questions.

I like a child in the street, was robbed of sugar by pedestrians, at a loss in the cold wind…..

Ok, let’s get started!

Here I do not say Handle source analysis, after all, source analysis online search a lot. Let’s get right to it!

Here’s what you’ll learn


1 . right H a n d l e Have some understanding of the process. That’s the point \color{blue}{1, have some understanding of Handle process. The important thing is this}

2. Learn about ThreadLocal, which is used to isolate data between threads. I’ll just talk about that a little bit.

3, along with understanding why thread blocking does not consume resources.

preparation

Class introduction, there are a few classes is enough.

Handler: controls the sending of messages and the callback of messages.
Looper: Basically looping to get the message.
Message: Message type definition.
MessageQueue: MessageQueue, which retrieves and enqueues messages
LooperTestMain: test entry, imitate the android app. ActivityThread.

Here is an introduction to the class code, which I’m sure you already know a lot about Handle.

Handler

Control message sending and message callback, as if there is nothing to say here, manual smile.

SendMessage Sends a message

HandleMessage handles messages

Notice that Handler is the message Handler as well as the message sender.

Part of the code is as follows:

public class Handler { public void sendMessage(int what, String msg) { queue.enqueueMessage(new Message(what, msg, this)); } public void handleMessage(Message message) { if(callback! =null){ callback.handleMessage(message); }}}Copy the code

Looper- Loops to fetch the message

It’s basically looping around to get the message, and notice the ThreadLocal here. What a ThreadLocal does is each thread creates a copy of the variable, which has a ThreadLocalMap with its own ThreadLocal key, and the thread calls get(), Returns a member variable in the current thread.

Queue.next () in loop(), where it will block until there is a message, and then pull it out.

Does blocking consume system resources?

Blocking will release system resources, here to involve some knowledge of the operating system, I will go to learn the knowledge of the operating system for a few days first.

Process status four

Execute ready, block (or wait), die. Different systems may differ, but they are generally the same.

Blocked: The state in which a process is suspended due to an event (such as an I/O request, request for buffer space, etc.), i.e. the process is blocked.

This state is called the blocking state, sometimes called the “waiting” state or the “sleeping” state. Generally, the processes in the blocked state are arranged in a queue, called a blocking queue. In some systems, blocked processes are queued in multiple ways, depending on the reason for blocking.

Here is the single-core operating system description:

Compare processes to people

For example, if you use one bathroom for 6 people, why one bathroom? Because multiple processes are executed alternately at the micro level. So 6 people take turns using one bathroom, this is called multi-threaded release, because the system multi-process is a time slice, that is, each person can only use for a while, for example, 30 seconds, then have to move on to the next. At this time pull half how to do? This is when you need to clip (this is the system interrupt mechanism \color{blue}{system interrupt mechanism} system interrupt mechanism, process management block PCB, will save the person pulled there, waiting for the next time to go to the bathroom). And then the next one, and so on.

It’s a waste of resources, if three of them are not in a hurry or have no need at all, it’s a waste of resources. So this time there is optimization, no demand, first wait outside. (this is the blocked state \color{blue}{blocked state} blocked state), put these three people in the blocked queue, then the bathroom pressure is reduced by half, you can happily go to the bathroom. Wait for them to have demand again again line up, at next….. That is, the blocked state becomes the ready state, queued, waiting for the system to allocate time slices – the execution state.

With the addition of the thread concept, a modern system can have more than one thread in a process, and a multi-core computer (multiple washrooms ~_~) can execute multiple threads simultaneously, which greatly increases efficiency. (Cup directly full ah!) Switching processes is expensive, switching threads is cheap. For example, if you put three people in the toilet, that is, next to the toilet, the process is less open and close the door, isn’t it more efficient? Manual smile. Let’s not talk about it. Save for the next article!

public class Looper { private static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>(); public MessageQueue queue ; private Looper() { queue = new MessageQueue(); } public static void initLooper() { if (sThreadLocal.get() ! = null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper()); } public static Looper getLooper() { return sThreadLocal.get(); } public static void loop() { Looper me = getLooper(); // Looper for (; ;) {// There is no message, it will block. Message message = me.queue.next(); if (message.target ! = null) { message.target.handleMessage(message); }}}}Copy the code

Message Message entity class

Message entity class

public class Message { public Handler target; public int what; public String message; public Message(int what, String massage,Handler target) { this.what = what; this.message = massage; this.target=target; }}Copy the code

MessageQueue MessageQueue

A message BlockingQueue, using an existing BlockingQueue.

Two functions: extract message and enqueue message.

Public class MessageQueue {private final BlockingQueue<Message> queue = new ArrayBlockingQueue<Message>(10); Public Message next() {try {return queue.take(); } catch (InterruptedException e) { e.printStackTrace(); } return null; Public void enqueueMessage(Message MSG) {try {queue.put(MSG); } catch (InterruptedException e) { e.printStackTrace(); }}}Copy the code

LooperTestMain Test entry

So far we’ve finished our code, and now we’re ready to test it. We set up the main method for the test. steps

1, which initLooper ()

2, create a Handle and add a message interceptor. If the interceptor returns true, the message will be intercepted and the handleMessage will not be received.

3, send messages through the child thread! sendMessage

4 stars), the loop (); Block fetch message, cannot let the thread exit. If the thread exits, subsequent events cannot be processed. Same with App ActivityThread.

public class LooperTestMain { public static void main(String[] args) { Looper.initLooper(); Handler handler1 = new Handler(MSG -> {return false; }) { @Override public void handleMessage(Message message) { super.handleMessage(message); System.out.println("received a massage from:" + Looper.getLooper()); System.out.println("this message info:" + message.message); System.out.println("Main Thread id:" + Thread.currentThread().getId()); }}; // Send messages via child thread! new Thread() { @Override public void run() { super.run(); int i = 0; while (true) { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Sub Thread id:" + Thread.currentThread().getId()); handler1.sendMessage(1, "send a massage:" + i++); } } }.start(); // Block the fetching of the message. If the thread exits, no further events can be processed. App ActivityThread looper.loop (); // If this is executed, the loop fetch message is abnormal. Android. App. ActivityThread. The last line of the main method in Java are written as such. throw new RuntimeException("Main thread loop unexpectedly exited"); }}}Copy the code
Full code address

The code address

conclusion

To sum up, read more and write more.

My knowledge is limited, if there is a description of the error, I hope the tiger is right. The story is fiction, and any resemblance is pure coincidence.

Look at thisLike you owe me a thumbs up. Thank you very much. Your praise is like the warm sun in winter, warming my heart.