我正在使用来自Guava的ListenableFuture,关于它们的一件好事是,将Executor传递给该Futures.addCallback
方法,即要求在给定的线程/执行器上执行回调。
在我的Android应用程序中,我希望能够基于ListenableFuture
UI线程启动异步执行,并计划一个也在UI线程上执行的回调。因此,我想以某种方式将UI线程执行器提交给上述Futures.addCallback
方法。如何实现呢?
或者,换句话说,我想要UI线程的执行程序。它已经在Android中可用,或者,如果我必须创建自己的,我该怎么做?
编辑: 作为对此问题的扩展,是否可以做同样的事情,但不仅可以使用UI线程,而且可以使用对调用异步方法的任何特定线程进行?
我很高兴知道如何仅使用纯Java 而无需借助Android专用的东西(如Handler
和)来达到相同的效果Looper
。
我想我已经看到一些实现方式。基本思路大致是
class UiThreadExecutor implements Executor {
private final Handler mHandler = new Handler(Looper.getMainLooper());
@Override
public void execute(Runnable command) {
mHandler.post(command);
}
}
通过将其传递给主线程的处理程序,您可以委派运行任何内容。
编辑:例如https://github.com/square/retrofit/blob/master/retrofit/src/main/java/retrofit/android/MainThreadExecutor.java
Edit2:您可以配置处理程序,例如SensorManager#registerListener(..., Handler handler)
允许您这样做。
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-
new ExecuteOnCaller()
而且通常不是您稍后运行代码的线程。
我很高兴知道如何仅使用纯Java就无需使用诸如Handler和Looper之类的Android特有的东西就能达到相同的效果。
Looper
,Handler
和后面所有的逻辑消息队列由大多纯Java的。通用解决方案的问题在于,您无法“注入”代码以运行到线程中。线程必须定期检查某种任务队列,以查看是否有要运行的东西。
如果您编写类似的代码
new Thread(new Runnable() {
@Override
public void run() {
while (!Thread.interrupted()) {
System.out.println("Hello");
}
}
}).start();
然后,除了不断打印“
Hello”之外,没有其他方法可以使该线程执行任何其他操作。如果可以的话,这就像在程序代码中动态插入到其他代码的跳转一样。IMO将是一个可怕的想法。
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();
另一方面,一个简单的线程会在队列中永远 循环 。该线程可以在两者之间执行其他任务,但是您必须在代码中添加手动检查。
您可以通过发送任务
queue.put(new Runnable() {
@Override
public void run() {
System.out.println("Hello!");
}
});
这里没有定义特殊的处理程序,但这是Handler&Looper在Android中所做的工作的核心。Handler
在Android中,您可以为Message
而不是定义回调Runnable
。
Executors.newCachedThreadPool()
和类似的东西大致相同。在一个队列中只有多个线程在等待代码。
作为对此问题的扩展,是否可以做同样的事情,而不仅是使用UI线程,而是使用任何特定线程来调用异步方法?
通用答案是“否”。仅当有一种方法可以注入代码在该线程中运行时。
主要内容:1 什么是Java currentThread()方法,2 Java currentThread()方法的语法,3 Java currentThread()方法的例子1 什么是Java currentThread()方法 Java currentThread() 方法返回当前正在执行的线程的引用。 2 Java currentThread()方法的语法 3 Java currentThread()方法的例子 输出结果为:
我确信这两个列表都不是空的,并且正在调用,但是没有调用order execution run方法....
我使用(全局声明)同时运行多线程。需要一个小时才能完成任务。因此,我需要获得当前运行的线程详细信息,如活动线程,排队线程和完成线程。 但事情是我需要停止在15分钟内发送新的请求到服务器或调用一些方法。 这里shutdown或shutdowNow停止执行器,但不停止这5个线程。这就是问题所在。所以我需要手动杀死那些线程。如何杀死executor服务中手动附加的线程?
我如何启动两个线程,其中thread1首先执行,thread2在thread1结束时启动,而主方法线程可以在不锁定其他两个线程的情况下继续工作? 我尝试了join(),但是它需要从线程调用,线程必须等待另一个线程,没有办法执行类似thread2.join(thread1)的操作;因此,如果我在main()中调用join,我将有效地停止主线程的执行,而不仅仅是Thread2的执行。 #编辑:为什么我
问题内容: 说我有以下代码: 现在,如果抛出,我该如何捕捉?一种方法是提供自己的实现,并为其中的设置custom 。另一种方法是将其包装为包含try-catch -block 的本地(匿名)。也许还有其他类似的解决方法。但是…以某种方式感觉很脏,我觉得这不应该那么复杂。有没有干净的解决方案? 问题答案: 干净的解决方法是使用而不是。这将返回一个,您可以用来检索结果或任务异常:
问题内容: 我尝试从一本书(Paul Hyde,Java Thread Programming)中运行示例。它说线程的顺序将互换。但是我总是得到:之后打印10个“主线程”,然后打印10个“新线程”。更有趣的是:如果我将使用tt.run而不是tt.start,那么结果将相反。也许这本书太老了,示例基于JDK 1.2的原因???代码如下: 问题答案: JVM决定何时将控制权从主线程转移到第二个线程。由