Interaction and collaboration between threads
Although the thread and thread share the memory space, that is, they can access the heap space of the process, but the thread has its own stack, method calls running in a thread are all in the thread's own call stack. Generally speaking, the West thread is a run () method and the method called internally. All method calls here are independent of other threads. Because of the relationship between method calls, another method is called by one method, and another method also occurs in the thread of the caller. Therefore, a thread is a time series concept, essentially a column of method calls.
To collaborate between threads, or to change the thread where a method is located (in order not to block its own thread), the thread can only send a message to another thread, and then return; in addition, the thread executes some operations after receiving the message. If a simple operation can be identified by a variable, for example, when thread a needs thread B to do something, a certain object OBJ can be set. Then, when thread B sees OBJ! = NULL. This type of thread interaction and collaboration has many examples in Java programming ideas.
ITC-Inter thread communication in Android
Note: Of course, handler can also be used as a message loop within a thread, without having to communicate with other threads. But here we will focus on the tasks between threads.
Android imposes a special restriction that the non-main thread cannot operate the UI elements, and an application cannot create derivative threads, in this way, the main thread and the derivative thread must communicate. Because of this frequent communication, it is impossible to identify all variables, and the program will become very messy. At this time, the Message Queue becomes very necessary, that is, to create a message queue in each thread. When a requires B, A sends a message to B. In essence, a adds the message to B's message queue. A returns this message, and B does not wait for a message, instead, you can view the Message Queue cyclically and execute the message after seeing the message.
The basic idea of the entire ITC is to define a message object, put the required data into it, and define the message processing method as Callback and put it into the message, then, the message is sent to another thread. The other thread processes the messages in Its Queue cyclically. When the message is displayed, the callback attached to the message is called to process the message. As a result, it can be seen that this only changes the execution sequence of the Message Processing: normally, it is processed on the spot, which is encapsulated into a message and thrown to another thread and executed at an uncertain time; in addition, the thread only provides the CPU time sequence, and does not interfere with what the message is and how the message is processed. In short, a method is put into another thread for calling, and the call stack of the caller of this method ends, the call stack of this method is transferred to another thread.
So what is the change in this mechanism? From the above, we can see that it only arranges one method (Message Processing) to another thread for (asynchronous processing), instead of doing it immediately, it changes the execution sequence of the CPU ).
So where is the message queue stored? It cannot be placed in the heap space (New messagequeue (). In this way, the object reference is easy to lose and it is not easy to maintain for the thread. JAVA supports threadlocal local storage of threads. Through threadlocal objects, you can place objects in the thread space. Each thread has its own object. Therefore, you can create a message queue for each thread to communicate with and store it in its local storage.
This model can also be extended, such as defining priority for messages.
Messagequeue
Messages are stored in a queue. Two operations are performed: enqueuemessage and next (). thread security is required, because columns are usually called by another thread.
Messagequeue is a mechanism very close to the underlying layer, so it is not convenient for developers to use it directly. To use this messagequeue, there must be two aspects of work. One is the target thread end: creation, associated with the thread, the other is the client of the queue thread: Creates a message, defines callback processing, and sends a message to the queue. Logoff and handler are encapsulation of messagequeue: logoff is used for the target thread. The purpose is to create messagequeue, associate messagequeue with the thread, and run messagequeue, logoff has a protection mechanism to allow a thread to create only one messagequeue object, while handler is used for the queue client to create a message, define the callback and send a message.
Because the logoff object encapsulates the target queue thread and Its Queue, for the client of the queue thread, The logoff object represents a thread with messagequeue and the messagequeue of the thread. That is to say, when you build a handler object, you use a logoff object. When you test whether a thread is the expected thread, you also use a logoff object.
Loggin
The logoff task is to create a message queue messagequeue, put it in threadlocal of the thread (associated with the thread), and run the messagequeue in ready state, the interface must be provided to stop the message loop. It has four main interfaces:
- Public static void lorule. Prepare ()
This method creates a loose object and messagequeue object for the thread, and puts the loose object into the thread space through threadlocal. Note that this method can only be called once by each thread. The common practice is in the first sentence of the thread run () method, but you only need to ensure that it is before loop.
- Public static void logoff. Loop ()
This method must be called after prepare () to run the messagequeue of the thread. Once this method is called, the thread will loop infinitely (while (true) {...}), sleep when there is no message, and wake up when there is a message in the queue until quit () is called. Its Simplified Implementation is:
loop() { while (true) { Message msg = mQueue.next(); if msg is a quit message, then return; msg.processMessage(msg) } }
- Public void loid. Quit ()
Let the thread end the messagequeue loop and terminate the loop. The run () method ends and the thread stops. Therefore, it is an object method, meaning to terminate a loose object. You must remember to call this method when you do not need a thread. Otherwise, the thread will not terminate and exit, and the process will continue to run, occupying resources. If a large number of threads do not exit, the process will eventually collapse.
- Public static logoff lorule. mylogoff ()
This is the method to obtain the logoff object owned by the caller's thread.
There are two other interfaces related to the main thread:
- One is specially prepared for the main thread
Public static void loid. preparemainlooper ();
This method is only used to initialize logoff for the main thread. It is only used in activitythread. the main () method cannot be called elsewhere or by other threads. if an exception is thrown when called in the main thread, a thread can only create one logoff object. However, if this method is called in other threads, The mainlooper will be changed. The next getmainlooper will return it instead of the looper object of the real main thread. This will not throw an exception, there will be no obvious errors, but the program will not work normally, because the method originally designed to run in the main thread will be transferred to this thread, it will produce a very strange bug. Here, the lorule. preparemainthread () method should include the following judgment:
public void prepareMainLooper() { if (getMainLooper() != null) { throw new RuntimeException("Looper.prepareMainthread() can ONLY be called by Frameworks"); } //... }
To prevent unauthorized calls by other threads, it is far from sufficient document constraints.
- The other interface is to get the Logoff of the main thread:
Public static Looper. getmainlooper ()
This is mainly used to check the thread validity, that is, to ensure that some methods can only be called in the main thread. But this is not safe. As mentioned above, if a derivative thread calls preparemainlooper (), it will change the real mmainlooper. This derivative thread can pass the above detection, resulting in getmainlooper ()! = Mylogoff () detection becomes unreliable. So the viewroot method is to use thread to detect: mthread! = Thread. currentthread (); its mthread is used when the system creates viewroot. obtained by currentthread (). This method is more reliable to check whether it is the main thread, because it does not depend on the external, but trust the reference of the thread saved by itself.
Message object
Message is only a data structure and a carrier of information. It has nothing to do with the queue mechanism. It encapsulates the required information of the actions to be executed and the actions to be executed. What, arg1, arg2 and OBJ can be used to transmit data, while the message callback must be defined by handler. Why? Because a message is only a carrier, it cannot run itself to the target messagequeue. It must be operated by handler to put the message in the target queue, since it requires handler to be uniformly placed on messagequeue, handler can also be used to define the callback for processing messages. Note that the same message object can only be used once. Because the message is recycled after the message is processed, the message object can only be used once, messagequeue throws an exception when trying to use it again.
Handler object
It is designed to facilitate operations on the queue thread client and hide the complexity of direct operations on messagequeue. The main function of handler is to send messages to the messagequeue of the thread bound to the handler. Therefore, when constructing a handler, you must specify a logoff object, if this parameter is not specified, The logoff object of the caller's thread is obtained through logoff. It has many heavy-load send * message and post methods, which can be used to send messages to the target queue in multiple ways, send messages at the sending time, or put them in the queue's header;
It also has two functions: one is to create a message object through the obtain * system method, and the other is to define the callback mcallback and handlemessage for message processing. Since a handler may not send more than one message, these messages usually share the callback method of the handler. Therefore, in handlemessage or mcallback, we need to distinguish these different messages, usually by message. you can also use other fields as long as you can distinguish different messages. It must be noted that the messages in the message queue are independent and irrelevant. The message namespace is in the handler object, because the messages are sent and processed by the handler, therefore, only one handler object needs to distinguish different message objects. Broadly speaking, if a message has a processing method defined by itself, all messages are irrelevant. When a message is retrieved from the queue, the callback Method on it is called, there will be no naming conflicts, but the callback Processing Method of the messages sent by handler is handler. handlemessage or handler. mcallback, so there will be an impact, but the scope of the impact is also limited to the same handler object.
Because handler sends messages to the target queue and defines the callback for processing messages (processing messages), it only depends on the messagequeue of the thread, so handler can have any number, are bound to a messagequeue, and there is no limit on the number. Messagequeue has a limit on the number of threads, and each thread can have only one thread. messagequeue is created through logoff. In the threadlocal Of The logoff storage thread, there is a limit in logoff, and each thread can only create one. However, handler does not have this restriction. The creation of handler uses its constructor to provide only one logoff object, so there is no limit on the number of handler objects.
From: http://blog.csdn.net/hitlion2008/article/details/8194510