Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/194.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Otto进行线程间的通信:它会导致任何问题吗?_Java_Android_Multithreading_Otto - Fatal编程技术网

Java 使用Otto进行线程间的通信:它会导致任何问题吗?

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;

我在最新的Android项目中试用了Otto,它确实大大简化了对象之间的通信。但是,我不确定线程之间的通信是否存在任何隐藏的问题

这就是我所做的,使用enum创建了一个SingletonBus,以便可以在任何地方访问该总线:

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
}