How to switch threads for messages sent by eventbus?, Which Java Architect course is good

switch threads messages sent eventbus

EventBus So many years since its birth , It can be seen in many production projects . As you can see from the update log , Except for the small size , It's stable , It hasn't been updated in the past two years , The last update is just because it supports all JVM, Let it be used in more than Android On .

It's very stable , Stable enough to give a feeling , If you use EventBus What's the problem , That must be the wrong way you used it .

EventBus How to use , about Android The old driver said , It must be familiar , There's too much information , I won't go into that here .

stay Android Next , Thread switching is a very common and necessary operation ,EventBus In addition to being able to subscribe and send messages , It can also specify the thread that receives the message processing message .

in other words , No matter what you do post() What thread is the message in ,EventBus You can distribute messages to the thread you specify , It sounds very convenient .

But no matter how you switch , There are only a few cases :

  • UI Thread cutting sub thread .

  • Sub thread cutting UI Threads .

  • Sub thread cutting other sub threads .

When we use EventBus When registering a message , Can pass @Subscribe Annotation to complete the registration event , @Subscribe You can use the parameter threadMode To specify which thread to use to receive messages .

@Subscribe(threadMode = ThreadMode.MAIN)

fun onEventTest(event:TestEvent){

// Handling events

}

threadMode It's a enum, There are many modes to choose from :

  1. POSTING, The default value is , That thread sends is that thread receives .

  2. MAIN, Switch to the main thread to receive events .

  3. MAIN_ORDERED,v3.1.1 New properties in , Also switch to the main thread to receive events , But and MAIN There are some differences , I'll tell you more later .

  4. BACKGROUND, Make sure to receive events... In the child thread . The details are , If it's a message sent by the main thread , Will switch to the sub thread receive , And if the event itself is emitted by a child thread , The thread that sends the event message will be used directly to process the message .

  5. ASYNC, Make sure to receive events... In the child thread , But and BACKGROUND The difference is that , It does not distinguish whether the sending thread is a child thread , It's receiving events in different threads every time .

EventBus Thread switch of , The main method involved is EventBus Of postToSubscription() Method .

private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {

switch (subscription.subscriberMethod.threadMode) {

case POSTING:

invokeSubscriber(subscription, event);

break;

case MAIN:

if (isMainThread) {

invokeSubscriber(subscription, event);

} else {

mainThreadPoster.enqueue(subscription, event);

}

break;

case MAIN_ORDERED:

if (mainThreadPoster != null) {

mainThreadPoster.enqueue(subscription, event);

} else {

// temporary: technically not correct as poster not decoupled from subscriber

invokeSubscriber(subscription, event);

}

break;

case BACKGROUND:

if (isMainThread) {

backgroundPoster.enqueue(subscription, event);

} else {

invokeSubscriber(subscription, event);

}

break;

case ASYNC:

asyncPoster.enqueue(subscription, event);

break;

default:

throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);

}

}

You can see , stay postToSubscription() In the method , For our configuration threadMode Value is processed .

This code logic is very simple , Let's take a look at the details of their implementation .

2.2 Switch to the main thread to receive events

Want to receive messages in the main thread , Need configuration threadMode by MAIN.

case MAIN:

if (isMainThread) {

invokeSubscriber(subscription, event);

} else {

mainThreadPoster.enqueue(subscription, event);

}

The logic of this passage is very clear , It is judged that the main thread will directly handle the event , If it's a non main thread , Just use mainThreadPoster Handling events .

track mainThreadPoster Code for , The concrete logic code is in HandlerPoster Class , It has achieved Poster Interface , This is a common Handler, It's just its Looper Using the main thread 「Main Looper」, Messages can be distributed to the main thread .

In order to improve efficiency ,EventBus There are also some minor optimizations here , It's worth learning from .

In order to avoid frequent to main thread sendMessage(),EventBus The way to do this is to process as many message events as possible in one message , So we used while loop , Continue from message queue queue Get message from .

At the same time, in order to avoid occupying the main thread for a long time , interval 10ms (maxMillisInsideHandleMessage = 10ms) Will resend sendMessage(), Used to relinquish the execution rights of the main thread , Avoid creating UI Carton and ANR.

MAIN It can ensure the reception of events , In the main thread , It should be noted that , If the event is sent in the main thread , Then use MAIN Will directly execute . In order to make the development and configurable Chengdu higher , stay EventBus v3.1.1 Added MAIN_ORDERED, It doesn't differentiate between the current thread , It's all about using mainThreadPoster To deal with it , That is to say, I will walk once Handler The distribution of messages .

When events need to be processed in the main thread , Time consuming operations are not required , There's nothing to say , In addition to MAIN perhaps MAIN_ORDERED The choice of , It depends on the specific business requirements .

2.3 Switch to sub thread execution

Want messages to be processed in child threads , You can configure the threadMode by BACKGROUND perhaps AYSNC, They can all achieve , But there are some differences .

First look at it. BACKGROUND, adopt postToSubscription() The logic in can be seen in ,BACKGROUND The thread that will distinguish the current event , Is it the main thread , This is not the main thread that distributes events directly , If it's the main thread , be backgroundPoster To distribute Events .

case BACKGROUND:

if (isMainThread) {

backgroundPoster.enqueue(subscription, event);

} else {

invokeSubscriber(subscription, event);

}

break;

BackgroundPoster It has also been realized. P

《 A big factory Java Analysis of interview questions + Back end development learning notes + The latest architecture explanation video + Practical project source code handout 》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 Full content open source sharing

oster Interface , It also maintains a message queue implemented by linked list PendingPostQueue,

In some It's mentioned in the coding specification , Don't create threads directly , Instead, you need to use a thread pool .EventBus And follow the rules , stay BackgroundPoster in , I used EventBus Of executorService Thread pool object to execute .

In order to improve efficiency ,EventBus Processing BackgroundPoster when , There are also some tips worth learning .

You can see , stay BackgroundPoster in , When processing events thrown by the main thread , There will only be one thread at a time , To loop from the queue , Get event handling event .

adopt synchronized Synchronization lock to ensure the thread safety of queue data , Simultaneous utilization volatile Identification of the executorRunning To ensure that the execution state seen under different threads is visible .

since BACKGROUND When dealing with tasks , Only one thread will be used , however EventBus But it uses thread pool , It seems a little wasteful . But learn more about ASYNC The implementation of the , Just know how to make full use of thread pool .

And what I mentioned earlier threadMode equally , Most of them correspond to one Poster, and ASYNC Corresponding Poster yes AsyncPoster, There was no special treatment , All events , They are all brainless EventBus Of executorService This thread pool , This guarantees , Whatever the thread of the event , And the thread that receives the event , It must be different , It also guarantees that the event will be processed in the sub thread .

public void enqueue(Subscription subscription, Object event) {

PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);

queue.enqueue(pendingPost);

copyright:author[m0_ sixty-four million three hundred and eighty-three thousand ],Please bring the original link to reprint, thank you. https://en.javamana.com/2022/01/202201261520121994.html