当前位置: 首页 > 面试题库 >

捕获当前线程的执行程序

淳于恺
2023-03-14
问题内容

我正在使用来自Guava的ListenableFuture,关于它们的一件好事是,将Executor传递给该Futures.addCallback方法,即要求在给定的线程/执行器上执行回调。

在我的Android应用程序中,我希望能够基于ListenableFutureUI线程启动异步执行,并计划一个也在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特有的东西就能达到相同的效果。

LooperHandler和后面所有的逻辑消息队列由大多纯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决定何时将控制权从主线程转移到第二个线程。由