youtubers tesis sobre sirve que para libros investigaciones investigacion historia caracteristicas android multithreading android-asynctask executor

android - tesis - ¿Por qué mis hilos no se mueren y causan una pérdida de memoria?



tesis sobre youtube pdf (1)

Una aplicación mía está acumulando muchas instancias de Thread que el GC no puede recoger y eliminar. Esta pérdida de memoria bloquea la aplicación a largo plazo.

No estoy 100% seguro de dónde vienen, pero tengo una clara sensación de que el siguiente podría ser el código en cuestión:

public class UraHostHttpConnection extends AbstractUraHostConnection { private Handler uiThreadHandler = new Handler(Looper.getMainLooper()); private Executor taskExecutor = new Executor() { public void execute(Runnable command) { new Thread(command).start(); } }; private ConnectionTask task = null; @Override public void sendRequest(final HttpUriRequest request) { this.task = new ConnectionTask(); this.uiThreadHandler.post(new Runnable() { public void run() { task.executeOnExecutor(taskExecutor, request); } }); } @Override public void cancel() { if (this.task != null) this.task.cancel(true); } }

Este código me permite ejecutar varias conexiones HTTP en paralelo que no se bloquearán entre sí en el Executor AsyncTask defecto (que es solo una cola con hilos únicos).

Comprobé que las AsyncTask están llegando a sus métodos onPostExecute() y no solo se ejecutan para siempre. Después de inspeccionar algunos volcados de memoria, sospecho que los objetos de Thread envoltura no pararán de ejecutarse después de que se AsyncTask completado los AsyncTask .

¿Es posible que el código anterior siga siendo responsable de la pérdida de memoria o debería comenzar a buscar en otro lado?

Cualquier ayuda es apreciada.

Editar: Cabe señalar que sendRequest solo se llama una vez. Otras partes del código que no están en la muestra anterior se aseguran de eso.

Editar 2: la superclase se ve así:

public abstract class AbstractUraHostConnection { protected IUraHostConnectionListener listener = null; public void setListener(IUraHostConnectionListener listener) { this.listener = listener; } public abstract void sendRequest(HttpUriRequest request); public abstract void cancel(); }

El AsyncTask se ve así:

private class ConnectionTask extends AsyncTask<HttpUriRequest, Object, Void> { final byte[] buffer = new byte[2048]; private ByteArrayBuffer receivedDataBuffer = new ByteArrayBuffer(524288); @Override protected Void doInBackground(HttpUriRequest... arg0) { UraHostHttpConnection.taskCounter++; AndroidHttpClient httpClient = AndroidHttpClient.newInstance("IVU.realtime.app"); try { // Get response and notify listener HttpResponse response = httpClient.execute(arg0[0]); this.publishProgress(response); // Check status code OK before proceeding if (response.getStatusLine().getStatusCode() == 200) { HttpEntity entity = response.getEntity(); InputStream inputStream = entity.getContent(); int readCount = 0; // Read one kB of data and hand it over to the listener while ((readCount = inputStream.read(buffer)) != -1 && !this.isCancelled()) { this.receivedDataBuffer.append(buffer, 0, readCount); if (this.receivedDataBuffer.length() >= 524288 - 2048) { this.publishProgress(receivedDataBuffer.toByteArray()); this.receivedDataBuffer.clear(); } } if (this.isCancelled()) { if (arg0[0] != null && !arg0[0].isAborted()) { arg0[0].abort(); } } } } catch (IOException e) { // forward any errors to listener e.printStackTrace(); this.publishProgress(e); } finally { if (httpClient != null) httpClient.close(); } return null; } @Override protected void onProgressUpdate(Object... payload) { // forward response if (payload[0] instanceof HttpResponse) listener.onReceiveResponse((HttpResponse) payload[0]); // forward error else if (payload[0] instanceof Exception) listener.onFailWithException((Exception) payload[0]); // forward data else if (payload[0] instanceof byte[]) listener.onReceiveData((byte[]) payload[0]); } @Override protected void onPostExecute(Void result) { listener.onReceiveData(this.receivedDataBuffer.toByteArray()); listener.onFinishLoading(); UraHostHttpConnection.taskCounter--; Log.d(TAG, "There are " + UraHostHttpConnection.taskCounter + " running ConnectionTasks."); } }


Sustituye a ThreadPoolExecutor para tu Executor para que tengas control sobre el tamaño del grupo. Si ThreadPoolExecutor es básicamente un Ejecutor con métodos expuestos, puede ser simplemente un caso en el que el tamaño de grupo máximo predeterminado sea muy alto.

Documento oficial aquí .

Eche un vistazo en particular a:

setCorePoolSize(int corePoolSize) //Sets the core number of threads. setKeepAliveTime(long time, TimeUnit unit) //Sets the time limit for which threads may remain idle before being terminated. setMaximumPoolSize(int maximumPoolSize) //Sets the maximum allowed number of threads.

También hay una alternativa si quieres codificar menos (mejor idea dependiendo de cuánto control realmente quieras y cuánto código cambiarás para obtenerlo).

Executor taskExecutor = Executors.newFixedThreadPool(x);

donde x = el tamaño de tu grupo