2012-06-19 99 views
8

Tengo un archivo CSV muy grande (1GB +), tiene 100.000 líneas.Cómo dividir un archivo CSV en varios fragmentos y leer esos fragmentos en paralelo en el código Java

Necesito escribir un programa Java para analizar cada línea desde el archivo CSV para crear un cuerpo para una solicitud HTTP para enviar.

En otras palabras, necesito enviar 100.000 solicitudes HTTP que corresponden a las líneas en el archivo CSV. Va a ser muy largo si hago esto en un solo hilo.

Me gustaría crear 1,000 hilos para hacer i) leer una línea del archivo CSV, ii) crear una solicitud HTTP cuyo cuerpo contiene el contenido de la línea de lectura, y iii) enviar la solicitud HTTP y recibir respuesta.

De esta forma, necesito dividir el archivo CSV en 1.000 fragmentos, y esos fragmentos no deben tener líneas superpuestas entre sí.

¿Cuál es la mejor manera de dividir este procedimiento?

+1

* Tengo un archivo CSV muy grande (1GB +), tiene 100,000 líneas * para las computadoras de hoy en día no es grande en absoluto. Tener significativamente más hilos que CPU es un error si puedes saturar todas las CPU. Al final estaría vinculado en el departamento de IO, y enviar toneladas de solicitudes simultáneas a un servidor no es muy inteligente a menos que intente realizar un DoS. – bestsss

Respuesta

7

Leer simultáneamente un solo archivo en varias posiciones no le permitiría avanzar más rápido (pero podría ralentizar) usted abajo considerablemente).

En lugar de leer el archivo de varios subprocesos, lea el archivo de un único subproceso y paralelice el procesando de estas líneas. Un hilo de singe debería leer su CSV línea por línea, y poner cada línea en una cola. Múltiples hilos de trabajo deberían tomar la siguiente línea de la cola, analizarla, convertirla en una solicitud y procesar la solicitud al mismo tiempo según sea necesario. La división del trabajo se haría con un solo hilo, asegurando que no faltan líneas o superposiciones.

+0

¿Es posible hacer una operación dividida para dividirla en varios fragmentos del mismo tamaño antes de leer el archivo? Si es así, después de dividir el archivo, mirar múltiples hilos para leer fragmentos en paralelo sería más rápido que un solo hilo leer todo el archivo, ¿o sí? – JuliaLi

+0

@JuliaLi No, en realidad no: los archivos grandes a menudo ocupan varios bloques que se encuentran cerca unos de otros en un disco.Como los discos son mucho más rápidos para acceder a bloques consecutivos porque no hay necesidad de volver a colocar el cabezal magnético, leer un archivo grande del disco va mucho más rápido cuando se hace de forma consecutiva. – dasblinkenlight

4

Puede tener un hilo que lea las líneas del CSV y construya una Lista de líneas leídas. Cuando esto alcanza algún límite, p. 100 líneas para pasar esto a un grupo de subprocesos de tamaño fijo para enviar como una solicitud.

Sospecho que, a menos que su servidor tenga 1000 núcleos, es posible que el uso de 10-100 solicitudes simultáneas sea más rápido.

+0

Depende de cuánto tiempo tarde en obtener una respuesta HTTP. Si los servidores involucrados son lentos, la mayoría de los subprocesos estarán esperando E/S. – biziclop

+0

Si la red o el servidor es lento, usar tamaños de lote más grandes o solicitudes más pequeñas podría mejorar el tiempo de carga. Es imposible decir qué es óptimo sin probarlo. Mi punto era; no asuma que cuantos más hilos, mejor. –

+1

Eso es lo que quise decir. Como es más probable que su aplicación esté vinculada a E/S, una fórmula fija basada en el número de núcleos no va a funcionar, debe experimentar con lo que funciona mejor. (O escriba un sistema adaptable, que probablemente lo esté complicando demasiado). – biziclop

1

Haga que un hilo lea el archivo línea por línea y para cada línea leída, publique una tarea en un ExecutorService para realizar la solicitud HTTP para cada uno.

Leer el archivo de varios hilos no va a funcionar, ya que para leer la línea n, primero debe leer todos los demás. (Podría funcionar en teoría si su archivo contiene registros de ancho fijo, pero CSV no tiene un formato de ancho fijo.)

+0

puede inferir el final de la línea cuando conoce las columnas, es factible pero apenas vale la pena el esfuerzo. Entonces, si hay varias matrices de discos y archivos mapeados, múltiples hilos funcionarían (para la parte de lectura) – bestsss

+0

¿Es posible hacer una operación dividida para dividirla en múltiples fragmentos del mismo tamaño antes de leer el archivo? Si es así, después de dividir el archivo, observe varios hilos para leer fragmentos en paralelo. – JuliaLi

2

Leer CSV archivo en un solo hilo una vez que la línea de delegado esta línea a uno de los Thread disponible en la piscina por la construcción del objeto de su Runnable Task y pasarlo a Executors'ssubmit(), que será ejecutada de forma asíncrona.

public static void main(String[] args) throws IOException { 

     String fName = "C:\\Amit\\abc.csv"; 
     String thisLine; 
     FileInputStream fis = new FileInputStream(fName); 
     DataInputStream myInput = new DataInputStream(fis); 
     ExecutorService pool=Executors.newFixedThreadPool(1000); 
     int count = 0; // Concurrent request to Server barrier 

     while ((thisLine = myInput.readLine()) != null) { 
      if (count > 150) { 
       try { 
        Thread.sleep(100); 
        count = 0; 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      } 

      pool.submit(new MyTask(thisLine)); 
      count++; 
     } 

    } 
} 

Aquí su tarea:

class MyTask implements Runnable { 
     private String lLine; 
     public MyTask(String line) { 
      this.lLine=line; 

     } 

     public void run() { 
      // 1) Create Request lLine 
      // 2) send the HTTP request out and receive response 
     } 
} 
0

Java 8, que está prevista para el lanzamiento de este mes, se habrá mejorado el soporte para este través de corrientes paralelas y lambdas. Oracle tutorial en las transmisiones paralelas podría ser un buen punto de partida.

Tenga en cuenta que una trampa aquí es demasiado paralelismo.Para el ejemplo de recuperación de URL, es probable que sea una buena idea tener un número bajo de llamadas en paralelo. Demasiado paralelismo puede afectar no solo el ancho de banda y el sitio web al que se está conectando, sino que también correrá el riesgo de quedarse sin descriptores de archivo, que es un recurso estrictamente limitado en la mayoría de los entornos donde se ejecuta java.

Algunos marcos que pueden ayudarle son Netflix 'RxJava y Akka. Tenga en cuenta que estos marcos no son triviales y requerirá un esfuerzo para aprender.

Cuestiones relacionadas