Java 使用Otto进行线程间的通信:它会导致任何问题吗?
我在最新的Android项目中试用了Otto,它确实大大简化了对象之间的通信。但是,我不确定线程之间的通信是否存在任何隐藏的问题 这就是我所做的,使用enum创建了一个SingletonBus,以便可以在任何地方访问该总线:Java 使用Otto进行线程间的通信:它会导致任何问题吗?,java,android,multithreading,otto,Java,Android,Multithreading,Otto,我在最新的Android项目中试用了Otto,它确实大大简化了对象之间的通信。但是,我不确定线程之间的通信是否存在任何隐藏的问题 这就是我所做的,使用enum创建了一个SingletonBus,以便可以在任何地方访问该总线: public enum SingletonBus { INSTANCE; private static String TAG = SingletonBus.class.getSimpleName(); private Bus bus;
public enum SingletonBus {
INSTANCE;
private static String TAG = SingletonBus.class.getSimpleName();
private Bus bus;
private boolean paused;
private final Vector<Object> eventQueueBuffer = new Vector<>();
private Handler handler = new Handler(Looper.getMainLooper());
private SingletonBus() {
this.bus = new Bus(ThreadEnforcer.ANY);
}
public <T> void postToSameThread(final T event) {
bus.post(event);
}
public <T> void postToMainThread(final T event) {
try {
if(paused) {
eventQueueBuffer.add(event);
} else {
handler.post(new Runnable() {
@Override
public void run() {
try {
bus.post(event);
} catch(Exception e) {
Log.e(TAG, "POST TO MAIN THREAD: BUS LEVEL");
throw e;
}
}
});
}
} catch(Exception e) {
Log.e(TAG, "POST TO MAIN THREAD: HANDLER LEVEL");
throw e;
}
}
public <T> void register(T subscriber) {
bus.register(subscriber);
}
public <T> void unregister(T subscriber) {
bus.unregister(subscriber);
}
public boolean isPaused() {
return paused;
}
public void setPaused(boolean paused) {
this.paused = paused;
if(!paused) {
Iterator<Object> eventIterator = eventQueueBuffer.iterator();
while(eventIterator.hasNext()) {
Object event = eventIterator.next();
postToMainThread(event);
eventIterator.remove();
}
}
}
}
然后我创建并发布了这个事件:
@Subscribe
public void keyPairCreate(KeyPairCreateEvent keyPairCreateEvent) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
KeyPair keyPair = keyPairCreator.createKeyPair();
SingletonBus.INSTANCE.getBus().post(new KeyPairCreatedEvent(keyPair));
} catch(...){...}
}
});
thread.start();
}
并在创建密钥对时订阅事件以获取结果:
@Subscribe
public void keyPairCreated(KeyPairCreatedEvent keyPairCreatedEvent) {
Log.d(MainActivity.class.getName(), "Acquired keypair: " + keyPairCreatedEvent.getKeyPair());
//do stuff
}
我的问题是,它似乎在工作,但在使用Otto和ThreadEnforcer.any进行线程间通信时会有任何隐藏的错误吗?这种方法有什么问题吗?Otto中的调度队列是用ThreadLocal包装的,因此,如果您在处理订阅服务器方法中接收到的事件时考虑了并发性,则不会有问题。Otto中的调度队列是用ThreadLocal包装的,因此,如果您在订阅服务器方法中处理接收到的事件时考虑了并发性,那么就不会有问题。Otto在发布事件的同一线程中同步发送事件。ThreadEnforcer只是为了验证您是否从预期的线程调用了post方法。MAIN声明您仅从主线程发布。若您从后台线程使用ThreadEnforcer.MAIN和post,总线将抛出运行时异常,警告您不要做错事。使用ThreadEnforcer。基本上不会进行任何检查。您可以从任何线程发帖,但是,正如我已经说过的,您必须期望订阅者也可以从任何线程被调用 应用于您的代码意味着KeyPairCreatedEvent将从后台发布,并且keyPairCreatedKeyPairCreatedEvent订阅服务器也将在该后台线程中调用。如果两个后台线程和主线程处理相同的数据,则必须同步,否则可能导致不一致。如果希望在主线程中传递结果以避免同步,则需要使用Handler.post并从那里调用bus.post 或者,您也可以尝试一下,它使用与Otto相同的接口,但在主线程中调用订阅者,即使事件是从后台线程发布的 希望这能有所帮助。奥托在发布事件的同一线程中同步发送事件。ThreadEnforcer只是为了验证您是否从预期的线程调用了post方法。MAIN声明您仅从主线程发布。若您从后台线程使用ThreadEnforcer.MAIN和post,总线将抛出运行时异常,警告您不要做错事。使用ThreadEnforcer。基本上不会进行任何检查。您可以从任何线程发帖,但是,正如我已经说过的,您必须期望订阅者也可以从任何线程被调用 应用于您的代码意味着KeyPairCreatedEvent将从后台发布,并且keyPairCreatedKeyPairCreatedEvent订阅服务器也将在该后台线程中调用。如果两个后台线程和主线程处理相同的数据,则必须同步,否则可能导致不一致。如果希望在主线程中传递结果以避免同步,则需要使用Handler.post并从那里调用bus.post 或者,您也可以尝试一下,它使用与Otto相同的接口,但在主线程中调用订阅者,即使事件是从后台线程发布的
希望这有帮助。欢迎来到stackoverflow。上面的帖子可能会回答这个问题。但是多做一点解释可能有助于其他程序员理解它是如何工作的。或者对于任何建议或批评,一旦你获得足够的声誉,你可以利用评论来帮助stackoverflow。上面的帖子可能会回答这个问题。但是,多做一点解释可能有助于其他程序员理解它是如何工作的。或者,关于任何建议或批评,一旦你获得足够的声誉,你可以利用评论,以便在发布事件的同一线程中同步发送事件。这一点非常重要。奥托在发布事件的同一线程中同步发送事件。这是非常重要的。
@Subscribe
public void keyPairCreated(KeyPairCreatedEvent keyPairCreatedEvent) {
Log.d(MainActivity.class.getName(), "Acquired keypair: " + keyPairCreatedEvent.getKeyPair());
//do stuff
}