2

我有一个小代码,我在 doInBackground 中读取了一个包含 100 个项目的序列化文件,创建了一个 ArrayList 并从 doInBackground 返回。在 PostExecute 中,我只是将数组列表复制到另一个与 ListView 适配器绑定的 ArrayList 对象。

有了这个,我用 10 秒的计时器获得了 10-40% 的 cpu 使用率。

我删除了异步任务,并在 ui 线程中连续执行了 doInackgrounf 和 postExecute 工作,并且在顶级命令输出中我总是 < 5% cpu。

那么 AsyncTask cpu 饿了吗?

下面的更新是 myAsyncTask 中的代码

class MyAsyncTask extends AsyncTask<String, String, ArrayList<Info>> {

    @Override
    protected ArrayList<Info> doInBackground(String... params) {

        ArrayList<Info> arr_list = new ArrayList<Info>() {
        };
        try {
            File f = new File(mainApp.getFilesDir(), "");
            String[] paths = f.list();
            ArrayList<String> delfiles = new ArrayList<String>() {
            };
            long n = 0;

            if (paths == null)
                return arr_list;

            for (int i = 0; i < paths.length; i++) {
                try {
                    long fname = Long.valueOf(paths[i]);
                    if (fname > n)
                        n = fname;
                    delfiles.add(paths[i]);
                } catch (Exception e) {
                    continue;
                }
            }

            lastFileNum = n;

            if (n > 0) {

                File fp = new File(mainApp.getFilesDir(), String.valueOf(n));
                FileInputStream fos = new FileInputStream(fp);
                ObjectInputStream os;

                os = new ObjectInputStream(fos);
                int count = (Integer) os.readObject();

                for (int i = 0; i < count; i++) {
                    Info ai = (Info) os.readObject();
                    arr_list.add(ai);
                }

                os.close();
                fos.close();

            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return arr_list;
    }

    @Override
    protected void onPostExecute(ArrayList<Info> arr_list) {
        try{
            if (this.isCancelled()) {
                return;
            }
            if (arr_list != null && arr_list.size() > 0) {

                if (this.isCancelled()) {
                    return;
                }
                mainApp.Info_data.clear();

                for (int i = 0; i < arr_list.size(); i++) {
                    mainApp.Info_data.add(arr_list.get(i));
                }
                if (this.isCancelled()) {
                    return;
                }
                if (this.isCancelled()) {
                    return;
                }
                    adapter.notifyDataSetChanged();
            }
            if (this.isCancelled()) {
                return;
            }

        }
        catch(Exception e){

        }
    }

}

并使用 matk.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, str); 调用

4

2 回答 2

0

您不应该在 UI 线程上进行任何形式的长时间处理。这不利于用户体验,也不利于作为开发人员的您,您应该始终卸载任何类型的长时间处理。

@m0skit0 所说的并不完全正确,“使用 AsyncTasks 你会得到更多的 CPU 使用率,因为你会产生不同的线程”

从 Android 3.0 开始,使用 .execute() 运行的 Asynctask 确实会在 UI 线程之外运行,但会在单个“Asynctask 线程”上按顺序运行,因此如果您生成 10 个异步任务,每个等待一秒钟,则需要十秒钟才能完成所有任务,不是你所期望的。您必须明确告诉 Android 将它们生成为不同的线程,请参阅此处了解如何执行此操作。

关于功耗,最佳能效,至少在 ARM 设备上是将 CPU 内核加速到高速但很短的时间,然后将它们降回低频以便它们可以休眠。能够将执行压缩到很短的时间范围内是您想要尝试和做的以最小化功耗。

- 编辑 -

使用 matk.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, str); 执行 将为异步任务创建独特的线程,以便它们可以并行运行。老实说,在不知道使用什么调度程序来管理内核行为的情况下,这是一个很难回答的问题。我同意在调用 android 代码的情况下设置 asynctasks 肯定会产生大量开销。更好的选择是直接使用开销少得多的 java 线程,或者如果任务非常小,则完全摆脱开销并在 UI 上执行

您必须记住的是,Asynctask 是 Android 提供的一个实用程序,可以让您作为程序员的生活更轻松。因此,随着 CPU 利用率的显示,他们选择了可用性和功能而不是效率。就个人而言,我很少使用 Asynctasks 并自己手动线程化,因为这使我可以完全控制我的应用程序的行为和执行。

总结一下,恕我直言,

UI 线程的开销最小,但不能使用超过几微秒,这是由 android 强制执行的,即如果您尝试在 UI 上运行网络,它将崩溃线程是最复杂的,您必须手动配置和控制线程生命周期,并且执行任何 UI 更改都需要 Handles 之类的东西 Asyctask 是 google 提供的一个很好的易于使用的实用程序,它可以让您的生活更简单,但是,提供的功能会带来性能成本和设置开销

于 2013-08-06T11:12:15.013 回答
0

好吧,我能想到的几个原因:

  • 使用 AsyncTasks,您将获得更多的 CPU 使用率,因为您正在生成不同的线程,这些线程本身需要初始化和它们的 JVM CPU 时间(请记住,Java 线程由 JVM 管理)。
  • 您在更短的时间内专注于相同的工作(所有任务)(通过线程,您实际上是同时执行所有任务),因此显然 CPU 使用率必须更高(不会产生或破坏能量,只会转换) .
于 2013-08-06T10:59:58.907 回答