Current location - Music Encyclopedia - Earning online - Taking over the old project, I was lost in thought when I saw that all network requests were distributed through EventBus.
Taking over the old project, I was lost in thought when I saw that all network requests were distributed through EventBus.

Although the employment situation in the Internet industry is "quite severe" now, Zhang Xiaopang has succeeded in changing jobs and raising his salary.

on the first day of employment, the Leader said, you are new here, so get familiar with our project this week.

Zhang Xiaopang skillfully uses Git pull code to get to the local area, and the environment variables are configured. Finally, he runs the project. Looking at the data requested by the network in the project, he is deeply lost in thought ...

What kind of coquettish operation is it to request data from the child thread and then distribute the data to the main thread through the EventBus? Wouldn't that be a problem?

although EventBus can achieve low-coupling event communication among multiple modules, and can completely use EventBus for thread switching, decoupling is decoupling, but reliable projects will not do this at all.

However, since we talked about thread switching of EventBus, today we will talk about how to deal with thread switching when EventBus events are distributed. And what should be paid attention to when using it, and whether a large number of thread switches relying on EventBus will be efficient.

2.1 EventBus switching thread

EventBus has been found in many production projects for so many years since its birth. As can be seen from the update log, except for its small size, it is still very stable. It has not been updated in the past two years, and the last update was only because it supports all JVMs, so that its use scope is not limited to Android.

it can be said that it is very stable, so stable that people have a feeling that if something goes wrong when you use EventBus, it must be that you are using it in the wrong way.

the usage of event bus is certainly familiar to old Android drivers, and there are too many related materials, so I won't repeat them here.

that is to say, no matter what thread you are in when you post () the message, EventBus can distribute the message to the thread you specify, which sounds very convenient.

However, no matter how to switch, there are several situations:

When we register messages with EventBus, we can register events through @Subscribe annotation, and in @Subscribe, we can specify which thread to use to receive messages through the parameter threadMode.

threadMode is an enum, and there are many modes to choose from:

the thread switching of EventBus mainly involves the postToSubscription () method of eventbus.

as you can see, the threadMode value we configured is processed in the postToSubscription () method.

The logic of this code is very simple. Let's take a look at the details of their execution.

2.2 switch to the MAIN thread to receive events

to receive messages in the main thread, you need to configure threadMode as main.

The logic in this paragraph is clear. If it is judged that the main thread is the main thread, it will directly handle the event. If it is not the main thread, it will use mainThreadPoster to handle the event.

tracing the code of mainThreadPoster, the specific logic code is in the HandlerPoster class, which implements the Poster interface, which is an ordinary Handler, except that its Looper uses the "Main Looper" of the main thread, and can distribute messages to the main thread.

in order to improve efficiency, EventBus has also made some minor optimizations here, which is worth learning from.

in order to avoid sending message () to the main thread frequently, EventBus handles as many message events as possible in one message, so it uses a while loop to continuously get messages from the message queue.

at the same time, in order to avoid occupying the main thread for a long time, sendMessage () will be re-sent at an interval of 11 ms (maxmillinsidehandmessage = 11 ms) to give up the execution right of the main thread, so as to avoid UI jam and ANR.

MAIN can ensure the reception of the event. In the MAIN thread, it should be noted that if the event is sent in the main thread, it will be directly executed by using main. In order to make the development and configurable Chengdu higher, MAIN_ORDERED is added to EventBus v3.1.1, which will not distinguish the current thread, but will all be handled by mainThreadPoster, that is, the message distribution of Handler will inevitably go through.

When an event needs to be handled in the MAIN thread, it is not necessary to perform time-consuming operations. In addition, the choice of main or MAIN_ORDERED depends on the specific business requirements.

2.3 switching to sub-thread execution

To make messages processed in sub-threads, you can configure threadMode as BACKGROUND or AYSNC, both of which can be realized, but there are some differences.

Let's take a look at the BACKGROUND first. Through the logic in postToSubscription (), we can see that the BACKGROUND will distinguish whether the thread in which the current event occurs is the main thread or not, and the non-main thread will directly distribute the event. If it is the main thread, the backgroundPoster will distribute the event.

BackgroundPoster also implements the Poster interface, in which a message queue PendingPostQueue implemented by linked list is also maintained.

It is mentioned in some coding specifications that instead of creating threads directly, a thread pool is needed. EventBus also follows this specification. In BackgroundPoster, the executorService thread pool object of EventBus is used for execution.

in order to improve efficiency, EventBus also has some tips to learn when dealing with BackgroundPoster.

as you can see, in the BackgroundPoster, when dealing with the events thrown by the main thread, there will only be one thread at the same time to loop from the queue and get the event-handling events.

The thread safety of queue data is guaranteed by synchronized synchronization lock, and the executorRunning identified by volatile is used to ensure that the execution status seen under different threads is visible.

since BACKGROUND only uses one thread when processing tasks, EventBus uses thread pool, which seems a bit wasteful. However, we will not know how to make full use of the thread pool until we continue to understand the implementation of ASYNC.

like the threadMode described above, most of them correspond to a Poster, and the Poster corresponding to ASYNC is AsyncPoster, in which no special processing is done, and all events are mindlessly thrown to the thread pool of executorService of EventBus for processing, which ensures that the thread that generates the event and the thread that receives the event must be different anyway, and also ensures that the event will be handled in the child thread.

You should have understood BACKGROUND and ASYNC here. Although both can guarantee to receive processing events in the child thread, their internal implementations are different.

at the same time in the background, only one child thread will be used to circularly get events from the event queue and process them, that is, the execution efficiency of the previous events will affect the execution of the subsequent events. For example, if you distribute an event using the BACKGROUND but there is a time-consuming operation in front of the queue, you must wait for the events in front of the queue to be processed before continuing execution. So if you pursue the efficiency of execution, you can use ASYNC for events that will be executed immediately.

isn't it just good to use ASYNC? Of course, such a package of decisions will not be good. ASYNC also has its own problems.

ASYNC will mindlessly send tasks to the thread pool executorService, and this thread pool, if you don't configure it, is created by default using the Executors' newCachedThreadPool ().

here I'm going to talk about coding specifications again. It is not recommended to use Executors to create threads directly. One of the reasons for this is that the thread pool rejects tasks. NewCachedThreadPool will create an unbounded queue to store tasks that the thread pool can't handle temporarily. When it comes to unbounded queues, you can think of OOM when there are too many tasks (events).

this is indeed a real problem when EventBus uses ASYNC.

But in fact, developers are allowed to configure it themselves, and it is difficult to configure a reasonable thread pool rejection strategy. When rejecting, some tasks will be abandoned, that is, some events will be abandoned. Any abandonment strategy is inappropriate. This is manifested in the use of EventBus, which means that there is a logical error and the events that should be received cannot be received. So you see, the unbounded queue here is not suitable, but it is not suitable to use it. The only way is to use ASYNC as little as possible and only use it when necessary and reasonable.

basically, the thread switching of EventBus when distributing events is made clear here. In fact, it is written in many materials that they can switch threads, but the details of some uses are not clearly described. Just take this article to make the thread switching of EventBus directly clear.

EventBus is also a common high-frequency word on resumes. When I interview, I often ask the interviewer about how it switches threads. But because it is simple and easy to use, in fact, many times we ignore its implementation details.

that's all for today. to sum up:

1. EventBus can configure the thread that receives the event through threadMode.

2. both main and MAIN_ORDERED will receive events in the main thread, and the difference lies in whether to distinguish whether the thread where the event occurs is the main thread.

3. BACKGROUND ensures that the thread is received in the child thread, and it will process all the events through the thread pool with one thread loop. Therefore, the timing of event execution will be affected by the efficiency of event processing in front of the event queue.

4. ASYNC ensures that events are received in the child thread. Different from the BACKGROUND, ASYNC will send tasks to the thread pool every time and execute them through the scheduling of the thread pool. However, because the thread pool uses unbounded queues, it will lead to too many events to be processed by ASYNC, which will lead to OOM.