捕获当前线程的执行程序 [英] Capturing executor for current thread

查看:115
本文介绍了捕获当前线程的执行程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用来自Guava的ListenableFuture ,关于它们的一个好处是一次传递执行程序 Futures.addCallback 方法,即要求在给定的线程/执行程序上执行回调。

I'm using ListenableFuture from Guava, and one nice thing about them is that one pass Executor to the Futures.addCallback method, that is, ask to execute the callback on a given thread/executor.

在我的Android应用程序中,我希望能够在UI线程中基于 ListenableFuture 启动异步执行,并安排一个也在UI线程上执行的回调。因此,我想以某种方式将UI线程执行程序提交到上面提到的 Futures.addCallback 方法。如何实现?

In my Android application, I want to be able to start the asynchronous execution based on ListenableFuture in the UI thread, and schedule a callback which is also executed also on the UI thread. Therefore, I'd like to somehow submit the UI thread executor to the Futures.addCallback method mentioned above. How to achieve that?

或者,换句话说,我想拥有UI线程的执行程序。它是否已在Android中提供,或者,如果我必须创建自己的,我该怎么做?

Or, in other words, I want to have an executor for the UI thread. Is it available already in Android, or, if I have to create my own, how do I do that?

编辑:作为扩展对于这个问题,是否有可能做同样的事情,但不仅仅是UI线程,而是任何特定的线程,在那里调用异步方法?

As an extension to this question, is it possible to do same thing, but not just with UI thread, but with any particular thread, where the call to async method is made?

我很高兴知道如何实现相同的效果,而不诉诸Android特定的东西,如 Handler Looper ,只用纯Java。

I would be happy to know how to achieve the same effect without resorting to the Android-specific stuff like Handler and Looper, just with pure Java.

推荐答案

我想我已经看到了一些实现。基本的想法大致是

I think I've see some implementation doing that. The basic Idea is roughly

class UiThreadExecutor implements Executor {
    private final Handler mHandler = new Handler(Looper.getMainLooper());

    @Override
    public void execute(Runnable command) {
        mHandler.post(command);
    }
}

你可以委托在主线程中运行任何东西将它传递给主线程的处理程序。

You can delegate to run anything in the main thread by passing it to a handler for the main thread.

编辑: https://github.com/square/retrofit/blob/master/retrofit/src/main/java/retrofit/android/MainThreadExecutor.java 例如

Edit2:您可以配置处理程序,例如 SensorManager #registerListener(...,处理程序处理程序) 允许你这样做。

You can configure the handler like e.g. SensorManager#registerListener(..., Handler handler) allows you to do.

class HandlerThreadExecutor implements Executor {
    private final Handler mHandler;
    public HandlerThreadExecutor(Handler optionalHandler) {
        mHandler = optionalHandler != null ? optionalHandler : new Handler(Looper.getMainLooper());
    }

    @Override
    public void execute(Runnable command) {
        mHandler.post(command);
    }
}

使用当前线程的looper的优势在于它明确指出您使用的 Looper 。在你的解决方案中,你可以使用任何线程的Looper调用 new ExecuteOnCaller() - 这通常不是你以后运行代码的线程。

The advantage over using the current thread's looper is that it makes it explicit which Looper you use. In your solution you take the Looper of whatever thread calls new ExecuteOnCaller() - and that's often not the thread you run code in later.


我很乐意知道如何在不使用像Handler和Looper这样的特定于Android的东西的情况下实现相同的效果,只需使用纯Java。

I would be happy to know how to achieve the same effect without resorting to the Android-specific stuff like Handler and Looper, just with pure Java.

Looper Handler 以及后面的消息队列所有这些逻辑都是由大多数纯Java构成的。通用解决方案的问题在于您无法注入代码以运行到线程中。线程必须定期检查某种任务队列以查看是否有东西要运行。

Looper, Handler and the message queue behind all that logic are made of mostly pure Java. The problem with a generic solution is that you can't "inject" code to run into a thread. The thread must periodically check some kind of task queue to see if there is something to run.

如果您编写的代码如

    new Thread(new Runnable() {
        @Override
        public void run() {
            while (!Thread.interrupted()) {
                System.out.println("Hello");
            }
        }
    }).start();

然后除了不断打印Hello之外,没有办法让该线程做任何其他事情。如果你能做到这一点就像在程序代码中动态插入其他代码一样。这将是一个糟糕的主意。

Then there is no way to make that thread do anything else but constantly print "Hello". If you could do that it would be like dynamically inserting a jump to other code into the program code. That would IMO be a terrible idea.

    final BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                while (true) {
                    Runnable codeToRunInThisThread = queue.take();
                    codeToRunInThisThread.run();
                }
            } catch (InterruptedException ignored) {}
        }
    }).start();

另一方面,一个简单的线程循环永远在队列中。线程可以在其间执行其他任务,但您必须在代码中添加手动检查。

On the other hand is a simple thread that loops forever on a queue. The thread could do other tasks in between but you have to add a manual check into the code.

您可以通过

    queue.put(new Runnable() {
        @Override
        public void run() {
            System.out.println("Hello!");
        }
    });

这里没有定义特殊的处理程序,但这是Handler& Looper在Android中做。 Android中的处理程序允许您为消息定义回调,而不仅仅是 Runnable

There is no special handler defined here but that's the core of what Handler & Looper do in Android. Handler in Android allows you to define a callback for a Message instead of just a Runnable.

Executors.newCachedThreadPool()和类似做同样的事情。只有多个线程在一个队列中等待代码。

Executors.newCachedThreadPool() and similar do roughly the same thing. There are just multiple threads waiting on code in a single queue.


作为这个问题,是否有可能做同样的事情,但不仅仅是UI线程,而是任何特定的线程,在那里调用异步方法?

As an extension to this question, is it possible to do same thing, but not just with UI thread, but with any particular thread, where the call to async method is made?

通用答案是否定的。只有在有一种方法可以注入要在该线程中运行的代码时。

The generic answer is No. Only if there is a way to inject code to run in that thread.

这篇关于捕获当前线程的执行程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆