AsyncTasks不会被收集,导致其他AsyncTasks无法运行

我的应用程序使用了很多AsyncTasks。 毕竟它是一个网络应用程序。 当我跟踪Debug选项卡时,我注意到每个AsyncTask都说在它后面运行,在5个AsyncTasks之后,我无法启动任何AsyncTasks。 我通过将执行程序更改为THREAD_POOL_EXECUTOR来修复它,它允许合并15个线程。 但AsyncTasks仍显示为正在运行。

AsyncTasks中都有InputStreams,其中有BufferedReaders来读取JSON,但我从不在Streamer和Readers上调用close()方法。 这可能是它,或者AsyncTask在完成之后无论如何收集?

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

看到我对此表示赞赏,我将更明确地解释这一点

AsyncTasks都经历了他们的方法。 除了使用不同的BasicNameValuePairs之外,所有这些都以相同的方式BasicNameValuePairs 。 我100%确定代码中没有容易出错的错误。

以下是其中一个AsyncTasks的示例:

 private class RunningEvent extends AsyncTask { @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 values = new ArrayList(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"); } } } 

上面的例子有时会作为第6个AsyncTask ,它永远不会进入doInBackground()方法。 我相信这是SERIAL_EXECUTOR的5 Thread限制。 我通过将大多数AsyncTasks放在THREAD_POOL_EXECUTOR “解决”问题,但这只是避免它。

这些AsyncTasks永远不会停止运行并堵塞Executor的原因是什么?

android.os.AsyncTask附带两个内置执行程序。 如果使用SERIAL_EXECUTOR,则没有线程池,并且所有AsyncTask都按顺序一次执行一个。 如果使用THREAD_POOL_EXECUTOR(我想这是你在问题中提到的),这允许最多128个AsyncTask并行执行。

您在调试中引用和查看的数字5是底层线程池的corePoolSize(AKA .THREAD_POOL_EXECUTOR),它与maximumPoolSize不同。 查看AsyncTask源代码并了解如何实现threadpool:

 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

你在debug中看到的那些5 AsyncTask实际上是在完成并变为空闲但永不终止的核心线程上,你可以通过调用ThreadPoolExecutor.allowCoreThreadTimeOut(boolean)来改变这种行为。


关于SERIAL_EXECUTOR的更多故事

我说SERIAL_EXECUTOR不使用threadpool,这不是真的。 SERIAL_EXECUTOR确实将实际工作委托给THREAD_POOL_EXECUTOR,但是使用ArrayDeque来控制下一个任务的提交(如果上一个任务完成则提交下一个任务),查看源代码:

 private static class SerialExecutor implements Executor { final ArrayDeque mTasks = new ArrayDeque(); 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配置)。