AsyncTasks没有得到收集造成其他AsyncTasks不运行AsyncTasks

2023-09-04 10:15:57 作者:小手冰凉ゞ

我的应用程序使用了大量AsyncTasks的。这是一个Web应用程序毕竟。当我跟踪调试选项卡中,我发现每一个AsyncTask的说,它背后的运行,并在5 AsyncTasks,我不能启动任何AsyncTasks。我通过更改遗嘱执行人 THREAD_POOL_EXECUTOR ,允许15个线程进行合并固定它。但AsyncTasks仍显示为正在运行。

My app uses a lot of AsyncTasks. It is a web app after all. And when I keep track of the Debug tab, I notice every AsyncTask says running behind it and after 5 AsyncTasks, I can't start any AsyncTasks. I fixed it by changing the executor to THREAD_POOL_EXECUTOR which allows 15 threads to be pooled. But the AsyncTasks still show as running.

该AsyncTasks都在其中InputStreams和BufferedReaders在他们阅读的JSON,但我从来没有叫关闭()上的飘带和读者的方法。难道这是它,或者在它的完成,无论将AsyncTask的收集是什么?

The AsyncTasks all have InputStreams in them and BufferedReaders in them to read the JSON, but I never call the close() method on the Streamers and Readers. Could this be it, or will the AsyncTask be collected after it's finished no matter what?

如果是这样的交易,那么为什么我不能在我的应用程序运行超过5 AsyncTasks?

If that's the deal, then why can't I run more than 5 AsyncTasks in my app?

AsyncTasks 所有经过他们的方法。所有这些都建立在完全相同的方式,但不同的 BasicNameValuePairs 。我100%肯定没有容易犯的错误,在code制成。

The AsyncTasks all go through their methods. All of them are built the same exact way, except with different BasicNameValuePairs. I am 100% sure there is no easy mistake made in the code.

下面是AsyncTasks之一的示例:

Here is an example of one of the AsyncTasks:

private class RunningEvent extends AsyncTask<Void, Void, Response> {

    @Override
    protected void onPreExecute() {
        if (Constants.isOnline(getApplicationContext())) {
            super.onPreExecute();
        } else {
            Toast.makeText(getApplicationContext(),
                    "No internet connection", Toast.LENGTH_LONG).show();
            return;
        }
    }

    @Override
    protected Response doInBackground(Void... empty) {
        HttpClient client = new DefaultHttpClient();
        HttpPost post = new HttpPost(URL);

        try {
            List<NameValuePair> values = new ArrayList<NameValuePair>(5);
            values.add(new BasicNameValuePair("tag", "eventRunning"));
            values.add(new BasicNameValuePair("userid", String
                    .valueOf(response.user.userid)));
            post.setEntity(new UrlEncodedFormEntity(values));

            HttpResponse httpresponse = client.execute(post);
            HttpEntity entity = httpresponse.getEntity();
            InputStream stream = entity.getContent();

            Log.i("MenuActivity",
                    "Input streamed, parsing Gson for existing events");
            Gson gson = new Gson();
            Reader reader = new InputStreamReader(stream);

            eventresponse = gson.fromJson(reader, Response.class);
            return eventresponse;
        } catch (Exception e) {
            e.printStackTrace();
            Log.e("RunningEvent", "Error sending data to Server");
        }
        return null;
    }

    @Override
    protected void onPostExecute(Response result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
        Log.i("MenuActivity", "Binding button");
        if (eventresponse != null) {
            if (eventresponse.success == 1) {
                eventresponse.user = response.user;
                bActivity.setOnClickListener(new OnClickListener() {

                    public void onClick(View arg0) {
                        Intent i = new Intent("com.xxx.xxx.EVENT");
                        i.putExtra("response", eventresponse);
                        running = false;
                        switcher.cancel(true);
                        MenuActivity.this.finish();
                        startActivity(i);
                    }

                });
            } else {
                bActivity.setText("Nieuw activity");
                bActivity.setOnClickListener(new OnClickListener() {

                    public void onClick(View arg0) {
                        Intent i = new Intent("com.xxx.xxx.NEWEVENT");
                        i.putExtra("response", response);
                        running = false;
                        switcher.cancel(true);
                        MenuActivity.this.finish();
                        startActivity(i);
                    }

                });
            }
        } else {
            Log.i("RunningEvent", "Response is null");
        }
    }

}

上面的例子就是有时候会拼命地跑为公司第六届的AsyncTask ,它将永远不会进入 doInBackground()方法。我相信这是5 发的 SERIAL_EXECUTOR 限制。我固定的问题,通过将大部分 AsyncTasks THREAD_POOL_EXECUTOR ,但是这仅仅是避免它。

The example above is the sometimes gets runned as the 6th AsyncTask and it will never enter the doInBackground() method. I believe this is the 5 Thread limit of the SERIAL_EXECUTOR. I "fixed" the problem by putting most AsyncTasks in THREAD_POOL_EXECUTOR, but this is just avoiding it.

可能是什么原因,这些 AsyncTasks 从来没有停止运行,并堵塞了执行程序

What could be the reason that these AsyncTasks never stop running and clogging up the Executor?

推荐答案

android.os.AsyncTask 配有两个内置的执行者。如果使用SERIAL_EXECUTOR,没有线程池和所有的AsyncTask得到在以串行顺序一次执行一个。如果使用THREAD_POOL_EXECUTOR(我想这是你提到的问题是什么),这使得开到最大128 AsyncTask的并行得到执行。

android.os.AsyncTask come with two built-in executor. if using SERIAL_EXECUTOR, there is no threadpool and all AsyncTask get execute one at a time in serial order. if using THREAD_POOL_EXECUTOR (I suppose this is what you refer in the question), this allows up to maximum 128 AsyncTask get execute in parallel.

5号的,你从调试参考,并看到的是底层的线程池的corePoolSize(AKA。THREAD_POOL_EXECUTOR),这与maximumPoolSize不同。检查出AsyncTask来源$ C ​​$ C ,看看线程池的实现:

The number 5 you refer and see from debugging is the corePoolSize of underlying threadpool (AKA. THREAD_POOL_EXECUTOR), which is different from maximumPoolSize. check out AsyncTask source code and see how threadpool is implemented:

private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;
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);

查看ThreadPoolExecutor API 看到什么就是通过调用这个构造函数创建的默认线程池的行为。一般来说,的 corePoolSize是线程的数量,以保持在游泳池,即使它们是空闲的,除非allowCoreThreadTimeOut设置

Check out ThreadPoolExecutor API to see what is the default threadpool behavior created by calling this constructor. Generally speaking, corePoolSize is the number of threads to keep in the pool, even if they are idle, unless allowCoreThreadTimeOut is set.

这5 AsyncTask的你在调试看到实际上在其上完成,成为闲置的,但从来没有终止的芯线,可以通过调用ThreadPoolExecutor.allowCoreThreadTimeOut(boolean).

Those 5 AsyncTask you see in debug are actually on core threads which are finished and become idle but never terminated, you can alter this behavior by calling ThreadPoolExecutor.allowCoreThreadTimeOut(boolean).

我说SERIAL_EXECUTOR不使用线程池,这是不正确的。 SERIAL_EXECUTOR确实委托实际工作THREAD_POOL_EXECUTOR,但使用ArrayDeque控制提交的下一个任务(下一个任务被提交当且仅当previous任务完成),检查出的源:

I said SERIAL_EXECUTOR does not use threadpool, this is not true. SERIAL_EXECUTOR is indeed delegate the real work to THREAD_POOL_EXECUTOR, but using ArrayDeque to control the submission of next tasks (next task is submitted iff the previous task is finished), check out the source:

private static class SerialExecutor implements Executor {
    final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
    Runnable mActive;

    public synchronized void execute(final Runnable r) {
        mTasks.offer(new Runnable() {
            public void run() {
                try {
                    r.run();
                } finally {
                    scheduleNext();
                }
            }
        });
        if (mActive == null) {
            scheduleNext();
        }
    }

    protected synchronized void scheduleNext() {
        if ((mActive = mTasks.poll()) != null) {
            THREAD_POOL_EXECUTOR.execute(mActive);
        }
    }
}

所以,无论你使用SERIAL_EXECUTOR或THREAD_POOL_EXECUTOR,总有在线程池5所示的芯线,即使他们是成品,并成为闲置。然而,芯线(由corePoolSize构造)的数量不是线程的数量(由maximumPoolSize构造)目前在线程池运行

So whatever you use SERIAL_EXECUTOR or THREAD_POOL_EXECUTOR, there are always 5 core threads shown in threadpool even they are finished and become idle. However, number of core thread (configured by corePoolSize) is not the number of threads (configured by maximumPoolSize) currently running in threadpool.