【问题标题】:Multithreaded code in AsyncTask doInBackgroundAsyncTask doInBackground 中的多线程代码
【发布时间】:2015-11-08 06:38:09
【问题描述】:

在 android AsyncTask 类的 doInBackground() 函数中运行多线程代码是否会带来性能优势?这是我计划的粗略草图:

private class MyBackgroundTask extends AsyncTask<Integer, Integer, Integer>
{
    protected Integer doInBackground(Integer... vals)
    {
        Thread[] thrds = new Thread[NUM_THREADS];
        //Start all threads
        for(int i = 0; i < thrds.length; ++i)
        {
            thrds[i] = //Initialize threads
            thrds[i].start();
        }
        //Wait for all threads to finish
        for(int i = 0; i < thrds.length; ++i)
            thrds[i].join();
        //Post processing...
        return foo;
    }

    protected void onPostExecute(Integer res)
    {
        //Pass value back to UI class
    }
}

这会产生可以在多核设备上利用的新线程吗?例如,如果每个线程都在一个(非常大的)数组中搜索最大值,那么在多核设备上是否会提高性能?或者这会导致类似“多对一”的行为。

还有一件事,我想使用多线程而不是调用多个 AsyncTasks,因为多线程最终将处理域级处理。我强烈希望将域级处理与 UI 类分离,这样我就可以使用不同的 UI 重用域级类。

提前致谢。

【问题讨论】:

  • 有趣的问题,我也很好奇你是否可以通过利用多线程来加速任务。
  • 取决于任务。计算时优势明显(因为 num_cores 计算是同时进行的。但是如果你的线程正在访问一些低速资源(例如,相同的磁盘存储),它们甚至可以比单线程慢。如果只是内存扫描(在数组中寻找最大值)它取决于处理器架构,特别是缓存组织。核心的公共缓存将增加缓存未命中的数量。
  • @AterLux 您是指一般意义上的多线程,还是专门指 doInBackground() 函数中的多线程?
  • @nickandross 一般。不取决于线程开始的位置。请记住,AsyncTask 只是简单线程的信封,它也启动了另一个线程。虽然,这个线程在加入时会处于等待状态,不会消耗 CPU 资源。为了提高效率,您可以将计算从线程之一移到 doInBackground 本身。
  • @AterLux 谢谢。我实现了我的想法并查看了 Android Studio 中正在运行的线程和行为appears to be as you described。我启动了 4 个线程,还有一个用于 AsyncTask 的附加线程。

标签: java android multithreading android-asynctask


【解决方案1】:

您应该使用AsyncTask,使用Thread#start() 生成您自己的线程或使用java.util.concurrent.Executor。您不太可能希望将这些东西结合起来。

AsyncTask 类默认为您的进程提供一个不同于 UI 线程的线程。这样做的原因主要是为了确保任务总是按照它们开始的顺序完成。如果这对您来说不是问题,那么AsyncTask 允许您指定要在其上运行的任何其他Executor,并提供一个已经调整为具有理想大小的池以针对目标处理器上的内核数量进行调整的出色池.

像这样运行一系列任务:

AsyncTask[] tasks = ...
for (Task task : tasks) {
    task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
}

出于好奇,Android 平台内部的代码如下所示:

private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE = 1;

/**
 * An {@link Executor} that can be used to execute tasks in parallel.
 */
public static final Executor THREAD_POOL_EXECUTOR
        = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
                TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

【讨论】:

    【解决方案2】:

    在 android AsyncTask 类的 doInBackground() 函数中运行多线程代码是否会带来性能优势?

    不,对我来说,你的想法比普通的 AsyncTask 带来了更多的混乱,请参阅 Google 关于“异步任务有什么问题”的说法,例如 The Hidden Pitfalls of AsyncTask。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多