Proceso de multi-subprocesos Java (Android)

Estoy trabajando en la aplicación ( Matt's traceroute windows versión http://winmtr.net/ ) que crea múltiples subprocesos cada hilo tiene su propio proceso (que ejecutan el comando ping). ThreadPoolExecutor apagar todos los subprocesos después de algún tiempo (por ejemplo, 10 segundos)

ThreadPoolExecutor utiliza la cola de bloqueo (las tareas de mantenimiento antes de ejecutarse)

 int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors(); ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor( NUMBER_OF_CORES * 2, NUMBER_OF_CORES * 2 + 2, 10L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>() ); 

PingThread.java

 private class PingThread extends Thread { @Override public void run() { long pingStartedAt = System.currentTimeMillis(); // PingRequest is custom object PingRequest request = buildPingRequest(params); if (!isCancelled() && !Thread.currentThread().isInterrupted()) { // PingResponse is custom object // Note: // executePingRequest uses PingRequest to create a command // which than create a runtime process to execute ping command // using string response i am creating PingResponse PingResponse pingResponse = PingUtils.executePingRequest(request); if (pingResponse != null) { pingResponse.setHopLocation(hopLocation); // publish ping response to main GUI/handler publishProgress(pingResponse); } else Logger.error( "PingThread", "PingResponse isNull for " + request.toString() ); } } } 

Ahora si creo varios hilos diga más de 500 en un bucle y ejecute dentro del ejecutor de pool

Ejecución de subprocesos

 PingThread thread = new PingThread(params); poolExecutor.execute(thread); 

Sé que LinkedBlockingQueue contiene las tareas antes de ejecutarse. El proceso de cada hilo toma un máximo de 200 a 400ms pero generalmente es menos de 10ms

Qué estoy haciendo

 for (int iteration = 1; iteration <= 50/*configurable*/; iteration++) { for (int index = 0; index < 10/*configurable*/; index++) { PingThread thread = new PingThread(someParams); poolExecutor.execute(thread); } try { Thread.sleep(500); } catch (InterruptedException e) { Logger.error(false, e); } } 

50 iteraciones tomará cerca de 25 segundos, aquí tengo solamente hasta 40 respuestas del silbido de bala considere como pérdida debido al tiempo hacia fuera. Si aumenta la pérdida de iteraciones aumenta también (exponencialmente debido al aumento en el número de hilos)

Observación:

Estoy ejecutando esta aplicación en el Galaxy S6 que tiene 8 núcleos, el tamaño del pool de aplicaciones es de 16 y el tamaño máximo de la piscina es de 16 + 2, sé que el procesador ejecuta sólo un hilo a la vez, que comparte un tiempo cuántico para el procesamiento en paralelo.

Observando ThreadPoolExecutor en forma oportuna, veo muchas tareas en la cola, después de tiempo de espera todavía hay muchos hilos presentes en la cola debido a LinkedBlockingQueue

Si disminuyo el número de hilos, funciona bien, pero si aumenta, crea problemas

Problema:

  • Las respuestas de ping disminuyen cuando uso dispositivos con procesador de doble núcleo.
  • ¿Por qué hay muchos hilos presentes en la cola, donde cada hilo toma alrededor de 10 a 50ms (aumentar el tiempo de hilos aumentará uptp 300ms o más)?
  • Debe completar con en el tiempo dado, ¿por qué no?
  • ¿Cómo superar este problema?
  • ¿Debo utilizar ConcurrentLinkedQueue pero utiliza el productor / modelo del consumidor, de alguna manera ThreadPoolExecutor (pienso que es) utiliza este modelo también.
  • LinkedBlockingQueue contiene las tareas antes de ejecutarse (los hilos están inactivos o en cola), ¿cómo superar esto?
  • Al establecer Thread.MAX_PRIORITY para iteraciones posteriores no resuelve el problema (el hilo de iteración posterior está en cola)
  • La disminución del número de hilos resuelve el problema ¿por qué? Porque hay menos hilos presentes en la cola?
  • ¿Hay alguna manera de comprobar, si los hilos presentes en la cola los entretienen entonces ejecuta otros, sin bloquear otros hilos pero dentro del tiempo dado.
  • Agregar tiempo extra como 5 segundos no es una solución
  • Cambiar corePoolSize como en ¿Cómo obtener el ThreadPoolExecutor para aumentar los hilos a máximo antes de hacer cola? No está funcionando en mi caso.

Durante la prueba de memoria y el uso del procesador están en un límite.

Se requiere respuesta / ayuda detallada.

Editar

Cuando la aplicación entra en el fondo no hay pérdida y el uso de la CPU del usuario cae a 0-2%, mientras que en la aplicación de enfoque tuvo un 4-6% de uso de la CPU. ¿Es debido a la interfaz de usuario y otras cosas ralted, traté de eliminar todo el código innecesario también PingThread cambiado PingThread a PingTask

PingTask implements Runnable {/*....*/}

Nota: he creado una aplicación basada en java independiente utilizando el mismo código y funciona bien en el escritorio, así que podemos decir que es el problema específico de Android?

No estoy seguro de si esto es lo que causa todos los problemas, pero está creando una gran cantidad de hilos innecesarios.

Deberías reemplazar

 private class PingThread extends Thread { 

con :

 private class PingThread implements Runnable { 

O (usando un nombre más adecuado):

 private class PingTask implements Runnable { 

Es decir, las tareas enviadas a Executor s no se supone que son hilo ellos mismos. Funciona, porque un Thread implementa Runnable , pero lo está desperdiciando.

Observación:

Después de crear y observar una aplicación java independiente (logs) usando el mismo código, llegué a conocer lo siguiente:

  • De alguna manera, la arquitectura y / o procesador del sistema operativo Android está limitando el número de subprocesos.
  • LinkedBlockingQueue contiene las tareas antes de ejecutarse, por lo que si tenemos una larga cola más tarde los hilos en la cola tendrán que esperar más.
  • Aumentar / Dynamic corePoolSize y maxPoolSize está haciendo lo mismo, agregaron subprocesos en la cola
  • La aplicación utiliza un 4-6% de CPU, por lo que no podemos decir que la CPU está sobrecargando o utilizando recursos completos de la aplicación, pero cuando la aplicación entra en segundo plano (la GUI u otro SO relacionado y / o aplicaciones basadas en hilos pueden detenerse o interrumpirse) -3%.

Solución:

Para 50 iteraciones y 10 internos crea 500 hilos ahora hice dos cosas:

  • Aumentar el tiempo Thread.sleep(millis) con algunos cálculos implica.
  • Disminuye el número de subprocesos para cada iteración. Ahora estoy creando 10 hilos Math.ceil((double) 10 / 3) = 3 por lo que tenemos 3 secuenciales PingUtils.executePingRequest(pingRequest) para cada hilo es decir 3 * 3 = 9 sigue siendo 1 por lo que vamos a crear un hilo separado para el último solicitud. Para cada iteración en lugar de crear 10 hilos ahora estoy creando 4 hilos.
  • Utilizando este enfoque ahora tengo 200 subprocesos en lugar de 500 que resuelve el problema.

Los subprocesos crean un nuevo objeto único, mientras que runnable permite que todos los subprocesos compartan un objeto. Como tal, no debe extender Thread al intentar multithread, en su lugar utilizar Runnable:

 class RunnableDemo implements Runnable { private Thread thread; String threadName="My thread"; public void run() { //do your code from here 'logic' System.out.println("Threading is Running"); try { for(int i = 4; i > 0; i--) { System.out.println("Thread: "+threadName +" "+ i); // Let the thread sleep for a while. Thread.sleep(50); //sleep your content for xx miliseconds } } catch (InterruptedException e) { System.out.println("Thread " + threadName + " interrupted."); } System.out.println("Thread " + threadName + " exiting."); //finish your work here } public void start () { System.out.println("Starting " + threadName ); if (thread == null) { thread = new Thread (this); thread.start (); //This will call your run methods of Runnable } } } //test your thread from here public class TestThread { public static void main(String args[]) { RunnableDemo R1 = new RunnableDemo( "Thread-1"); R1.start(); RunnableDemo R2 = new RunnableDemo( "Thread-2"); R2.start(); } } 
  • Diferencia entre AsyncTask y Thread / Runnable
  • Android AsyncTask vs hilo + controlador vs rxjava
  • Android claro hilo webview, libre de memoria, evitar OutOfMemoryError
  • Ejecutar tareas en backgound en NativeScript
  • Sincronizar varias ventanas con varias vistas en Android
  • Android SQLite Query, insertar, actualizar, eliminar, siempre tiene que estar en el hilo de fondo?
  • Cómo llamar a las actividades de un hilo no actividad?
  • Diferencia entre MainThread, UiThread, WorkerThread, BinderThread en Android Annotation
  • Buenas prácticas para multi-threading
  • ¿Cómo implementar la función .get con FutureTask o BackgroundTask usando android?
  • Uso de OpenGL desde el hilo principal de Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.