Android AsyncTask 线程限制? [英] Android AsyncTask threads limits?

查看:21
本文介绍了Android AsyncTask 线程限制?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个应用程序,每次用户登录系统时我都需要更新一些信息,我也在手机中使用数据库.对于所有这些操作(更新、从数据库检索数据等),我使用异步任务.到目前为止,我不明白为什么我不应该使用它们,但最近我体验到,如果我执行一些操作,我的一些异步任务只会在执行前停止并且不会跳转到 doInBackground.把它留在那里太奇怪了,所以我开发了另一个简单的应用程序来检查出了什么问题.奇怪的是,当异步任务总数达到 5 时,我得到了相同的行为,第 6 个在预执行时停止.

I am developing an application where I need to update some info every time user logs in to the system, I also use database in the phone. For all those operations (updates, retrieving data from db and etc.) I use async tasks. As up till now I didn't see why I shouldn't use them, but recently I experienced that if I do some operations some of my async tasks simply stop on pre-execute and don't jump to doInBackground. That was just too strange to leave it like that, so I developed another simple application just to check whats wrong. And strange enough, I get the same behavior when count of total async tasks reach 5, the 6th one stops on pre-execute.

android 对 Activity/App 的 asyncTasks 有限制吗?还是只是一些错误,应该报告?有没有人遇到过同样的问题,也许找到了解决方法?

Does android have a limit of asyncTasks on Activity/App? Or is it just some bug and it should be reported? Did anyone experience the same problem and maybe found a workaround to it?

代码如下:

只需创建 5 个在后台工作的线程:

Simply create 5 of those threads to work in a background:

private class LongAsync extends AsyncTask<String, Void, String>
{
    @Override
    protected void onPreExecute()
    {
        Log.d("TestBug","onPreExecute");
        isRunning = true;
    }

    @Override
    protected String doInBackground(String... params)
    {
        Log.d("TestBug","doInBackground");
        while (isRunning)
        {

        }
        return null;
    }

    @Override
    protected void onPostExecute(String result)
    {
        Log.d("TestBug","onPostExecute");
    }
}

然后创建这个线程.它会进入 preExecute 并挂起(它不会去 doInBackground).

And then create this thread. It will enter preExecute and hang (it will not go to doInBackground).

private class TestBug extends AsyncTask<String, Void, String>
{
    @Override
    protected void onPreExecute()
    {
        Log.d("TestBug","onPreExecute");

        waiting = new ProgressDialog(TestActivity.this);
        waiting.setMessage("Loading data");
        waiting.setIndeterminate(true);
        waiting.setCancelable(true);
        waiting.show();
    }

    @Override
    protected String doInBackground(String... params)
    {
        Log.d("TestBug","doInBackground");
        return null;
    }

    @Override
    protected void onPostExecute(String result)
    {
        waiting.cancel();
        Log.d("TestBug","onPostExecute");
    }
}

推荐答案

所有 AsyncTasks 都由一个共享(静态)ThreadPoolExecutorLinkedBlockingQueue.当您在 AsyncTask 上调用 execute 时,ThreadPoolExecutor 将在未来某个时间准备就绪时执行它.

All AsyncTasks are controlled internally by a shared (static) ThreadPoolExecutor and a LinkedBlockingQueue. When you call execute on an AsyncTask, the ThreadPoolExecutor will execute it when it is ready some time in the future.

我什么时候准备好?"ThreadPoolExecutor 的行为由两个参数控制,核心池大小最大池大小.如果当前活动的线程少于核心池大小的线程并且有新作业进入,则执行程序将创建一个新线程并立即执行它.如果至少有核心池大小的线程在运行,它将尝试将作业排队并等待,直到有空闲线程可用(即,直到另一个作业完成).如果无法将作业排队(队列可以具有最大容量),它将创建一个新线程(达到最大池大小的线程)供作业运行.非核心空闲线程最终可以退役根据保持活动超时参数.

The 'when am I ready?' behavior of a ThreadPoolExecutor is controlled by two parameters, the core pool size and the maximum pool size. If there are less than core pool size threads currently active and a new job comes in, the executor will create a new thread and execute it immediately. If there are at least core pool size threads running, it will try to queue the job and wait until there is an idle thread available (i.e. until another job is completed). If it is not possible to queue the job (the queue can have a max capacity), it will create a new thread (up-to maximum pool size threads) for the jobs to run in. Non-core idle threads can eventually be decommissioned according to a keep-alive timeout parameter.

Android 1.6 之前,核心池大小为 1,最大池大小为 10.从 Android 1.6 开始,核心池大小为 5,最大池大小为 128.两种情况下的队列大小均为 10.keep-alive 超时时间是 2.3 之前的 10 秒,之后是 1 秒.

Before Android 1.6, the core pool size was 1 and the maximum pool size was 10. Since Android 1.6, the core pool size is 5, and the maximum pool size is 128. The size of the queue is 10 in both cases. The keep-alive timeout was 10 seconds before 2.3, and 1 second since then.

考虑到所有这些,现在很清楚为什么 AsyncTask 只会执行 5/6 的任务.第 6 个任务正在排队,直到其他任务之一完成.这是您不应该将 AsyncTasks 用于长时间运行的操作的一个很好的理由 - 它会阻止其他 AsyncTasks 运行.

With all of this in mind, it now becomes clear why the AsyncTask will only appear to execute 5/6 of your tasks. The 6th task is being queued up until one of the other tasks complete. This is a very good reason why you should not use AsyncTasks for long-running operations - it will prevent other AsyncTasks from ever running.

为了完整起见,如果您用超过 6 个任务(例如 30 个)重复练习,您将看到超过 6 个将进入 doInBackground 因为队列将变满并且执行器被推送到创建更多的工作线程.如果您继续执行长时间运行的任务,您应该看到 20/30 变为活动状态,还有 10 个仍在队列中.

For completeness, if you repeated your exercise with more than 6 tasks (e.g. 30), you will see that more than 6 will enter doInBackground as the queue will become full and the executor is pushed to create more worker threads. If you kept with the long-running task, you should see that 20/30 become active, with 10 still in the queue.

这篇关于Android AsyncTask 线程限制?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆