捕获当前线程的执行程序 [英] Capturing executor for current thread
问题描述
我正在使用来自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.
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屋!