2009-06-13 13 views
7

Tengo una aplicación que genera un nuevo hilo cuando un usuario solicita que se filtre una imagen.Simple Thread Management - Java - Android

Este es el único tipo de tarea que tengo y todos son de igual importancia.

Si solicito demasiados subprocesos simultáneos (Máx. Que siempre quiero es 9) el administrador de subprocesos arroja un RejectedExecutionException.

Por el momento lo que hago es;

// Manage Concurrent Tasks 
private Queue<AsyncTask<Bitmap,Integer,Integer>> tasks = new LinkedList<AsyncTask<Bitmap,Integer,Integer>>(); 

@Override 
public int remainingSize() { 
    return tasks.size(); 
} 

@Override 
public void addTask(AsyncTask<Bitmap, Integer, Integer> task) { 
    try{ 
     task.execute(currentThumbnail); 
     while(!tasks.isEmpty()){ 
      task = tasks.remove(); 
      task.execute(currentThumbnail); 
     } 
    } catch (RejectedExecutionException r){ 
     Log.i(TAG,"Caught RejectedExecutionException Exception - Adding task to Queue"); 
     tasks.add(task); 
    } 
} 

sólo tiene que añadir la tarea rechazada a una cola y la próxima vez que un hilo se inicia la cola se comprueba para ver si hay un retraso.

El problema obvio con esto es que si la tarea final se rechaza en su primer intento, nunca se reiniciará (Hasta después de que ya no se necesite).

Solo me pregunto si hay un modelo simple que debería usar para manejar este tipo de cosas. Necesito tareas para notificar a la cola cuando hayan terminado, así sé que hay espacio, pero no estoy seguro de cómo.

Saludos cordiales,

Gavin

Respuesta

12

El motivo de RejectedExecutionException es que AsyncTask implementa un grupo de subprocesos propio (según la respuesta del Sr. Martelli), pero que tiene un límite máximo de 10 tareas simultáneas. Por qué tienen ese límite, no tengo idea.

Por lo tanto, una posibilidad es clonar AsyncTask, aumentar el límite (o ir ilimitado, que también es posible con LinkedBlockingQueue), y usar su clon. Luego, tal vez, envíe el cambio como un parche al AsyncTask para futuras versiones de Android.

Haga clic en here para ejecutar una búsqueda de código de Google para AsyncTask - el primer golpe debería ser la implementación.

Si solo desea aumentar el límite, ajuste MAXIMUM_POOL_SIZE para que sea lo más grande que pueda necesitar. Si quiere ir sin límites, use el constructor LinkedBlockingQueue de argumento cero en lugar del que se usa actualmente. AFAICT, el resto del código probablemente se mantenga igual.

+15

El límite ya no es 10. El límite se estableció porque AsyncTasks no debe ser disparado por docenas. Dado que el objetivo de dicha tarea es actualizar la interfaz de usuario, sería bastante terrible tener docenas de subprocesos que causen actualizaciones. –

+0

El límite actual es de 5 subprocesos paralelos según http://google.com/codesearch#uX1GffpyOZk/core/java/android/os/AsyncTask.java –

+0

@Grantland Chew: No, es 5 para empezar. Puede crecer más allá de eso. – CommonsWare

3

Se parecen haber implementado una versión del patrón de diseño Thread Pool - El artículo señala Wikipedia para muchos artículos útiles sobre el tema, que pueden ayudar a refinar su aplicación. También recomiendo this Java-specific article que tiene un código claro y una explicación.

0

Tal vez una opción es tener la tarea en espera en una cola de bloqueo (de mapas de bits) en lugar de tomar el mapa de bits como un parámetro, pero tendrá que agregar una forma para que la (s) tarea (s) finalicen.