FutureTask提交给执行者不运行

时间:2012-12-13 01:48:11

标签: java android concurrency futuretask

我编写了一个类,其中一系列实例旨在从AsyncTask调用,它将返回runReport()方法的结果。它创建一个工作线程就好了,但由于某种原因,它不会执行Callable的call()方法。我做错了什么?

//Problem: doStuff() never gets called, even though the worker thread gets created.

@Override
public ReportResult runReport() throws InterruptedException, ExecutionException {
    Callable<ReportResult> report = new Callable<ReportResult>() {

        @Override
        public ReportResult call() throws Exception {
            doStuff();
            ...
            return new ReportResult(varWrittenByMethod);
        }
    };
    FutureTask<ReportResult> result = new FutureTask<ReportResult>(report);

    //I tried a few of these ExecutorService factory methods, with the same result.
    //I only made my own ThreadFactory to verify the worker was created
    ExecutorService es = Executors.newSingleThreadExecutor(new ThreadFact());
    es.submit(report);

    ReportResult finalResult = result.get();
    es.shutdownNow();
    return finalResult;
}


private class ThreadFact implements ThreadFactory{

    @Override
    public Thread newThread(Runnable r) {
        Log.d(TAG, "Created worker Thread");
        return new Thread(r);
    }

}

据我所知,我必须在它自己的Thread中作为FutureTask执行此操作,因为它需要执行以下操作(除了返回之外的所有内容都在doStuff()中):

  • 做一些重要的同步设置(AsyncTask保持关闭UI线程)
  • 致电Looper.prepare()
  • 注册听众
  • 调用Looper.loop(),在一段时间内从侦听器中捕获一些回调。
  • 当我有足够的数据点时,在侦听器回调中调用Looper.myLooper()。quit()
  • 返回结果

我愿意接受更好的方法。我最初让AsyncTask进行此调用,然后在其线程上运行Looper.loop(),但我无法处理这些对象的队列,因为我需要在返回结果之前从侦听器调用Looper.myLooper.quit() ,这不可逆转地毒害了线程的消息队列。

2 个答案:

答案 0 :(得分:3)

您的线程工厂不会将传递的Runnable传播到创建的线程。在ThreadFactory中,尝试:

return new Thread(r);

此外,您应该使用submit方法返回的FutureTask,而不是您明确创建的FutureTask。 E.g。

FutureTask<ReportResult> result = es.submit(report);
ReportResult finalResult = result.get();

答案 1 :(得分:2)

作为一个注释,您可能会后悔从AsyncTask执行此级别的工作,因为AsyncTask中的线程将在Activity生命周期更改期间被杀死。最好在IntentService中进行异步设置。如果你不需要Looper(),你可以使用普通线程而不是HandlerThreads。