2012-02-26 9 views
6

Estoy tratando de recorrer un iterador de Java al mismo tiempo, pero estoy teniendo problemas con la mejor manera de hacerlo.Java Iterator Concurrency

Esto es lo que tengo donde no trato de hacer nada al mismo tiempo.

Long l;  
Iterator<Long> i = getUserIDs(); 

while (i.hasNext()) { 
    l = i.next(); 

    someObject.doSomething(l); 
    anotheObject.doSomething(l); 
} 

No debe haber condiciones de carrera entre las cosas que estoy haciendo en los objetos no iterador, así que no estoy demasiado preocupado por eso. Simplemente me gustaría acelerar el tiempo que lleva recorrer el iterador al no hacerlo de forma secuencial.

Gracias de antemano.

Respuesta

4

Una solución es usar un ejecutor para paralelizar su trabajo.

ejemplo simple:

ExecutorService executor = Executors.newCachedThreadPool(); 

Iterator<Long> i = getUserIDs(); 
while (i.hasNext()) { 
    final Long l = i.next(); 

    Runnable task = new Runnable() { 
     public void run() { 
      someObject.doSomething(l); 
      anotheObject.doSomething(l); 
     } 
    } 

    executor.submit(task); 
} 

executor.shutdown(); 

Esto creará un nuevo hilo para cada elemento en el repetidor, que llevarán a cabo la obra. Puede sintonizar cuántos subprocesos se usan utilizando un método diferente en la clase Executors, o subdividir el trabajo como mejor le parezca (por ejemplo, un Runnable diferente para cada una de las llamadas a métodos).

5

A puede ofrecer dos enfoques posibles:

  • Utilice un grupo de subprocesos y enviar los artículos recibidos desde el repetidor a un conjunto de hilos de procesamiento. Esto no acelerará las operaciones del iterador en sí mismas, ya que aún ocurrirían en un solo hilo, pero paralelizará el procesamiento real.

  • Dependiendo de cómo se crea la iteración, que podría ser capaz de dividir el proceso de iteración a múltiples segmentos, cada uno para ser procesado por un hilo separado a través de un Iterator objeto diferente. Por ejemplo, eche un vistazo a los métodos List.sublist(int fromIndex, int toIndex) y List.listIterator(int index).

    Esto permitiría que las operaciones del iterador ocurrieran en paralelo, pero no siempre es posible segmentar la iteración de esta manera, generalmente debido al simple hecho de que los elementos a iterar no están disponibles inmediatamente.

  • Como truco de bonificación, si las operaciones de iteración son caras o lentas, como las requeridas para acceder a una base de datos, puede ver una mejora en el rendimiento si las separa en un hilo separado que usará el iterador para rellenar en un BlockingQueue. El hilo del despachador solo tendrá que acceder a la cola, sin esperar al objeto del iterador para recuperar el siguiente elemento.

El consejo más importante en este caso es la siguiente: "Use su generador de perfiles", por lo general a ser seguido por "No te optimizar prematuramente". Mediante el uso de un generador de perfiles, como VisualVM, debe poder determinar el exacto causa de cualquier problema de rendimiento, sin tomar fotos en la oscuridad.

1

Si está utilizando Java 7, puede usar el nuevo fork/join; ver el tutorial.

No solo divide automáticamente las tareas entre los subprocesos, pero si un subproceso finaliza sus tareas antes que los otros subprocesos, "roba" algunas tareas de los otros subprocesos.