Foros del Web » Programación para mayores de 30 ;) » Java »

[SOLUCIONADO] Sincronizacion hilos - Escritura txt

Estas en el tema de Sincronizacion hilos - Escritura txt en el foro de Java en Foros del Web. Buenas! Tengo un programa de java que consta de un programa principal y multiples hilos que busca apariciones de palabras en los ficheros de texto ...
  #1 (permalink)  
Antiguo 09/10/2014, 04:24
Avatar de calathea  
Fecha de Ingreso: octubre-2008
Ubicación: Valladolid
Mensajes: 122
Antigüedad: 15 años, 9 meses
Puntos: 3
Sincronizacion hilos - Escritura txt

Buenas!

Tengo un programa de java que consta de un programa principal y multiples hilos que busca apariciones de palabras en los ficheros de texto de un directorio.

---> Programa Principal:
  • Recibe como argumentos el directorio de trabajo donde se encuentran los ficheros .txt y la palabra que queremos buscar en ellos.
  • Creará un fichero de texto vacío para recoger los resultados de la búsqueda y lanzará un hilo por cada fichero de txt.
  • Finalmente, cuando todos los hilos han acabado, el programa principal escribirá por consola el contenido completo del fichero de resultados.

---> Hilo:
  • Cada hilo buscará apariciones de la palabra en el fichero de texto que le asignemos.
  • Con cada aparición, incorporará en el fichero de resultados:
    • una línea con el nombre del fichero original y el número de línea en la que se encuentra dentro de dicho fichero
    • una segunda línea con el contenido de la línea completa donde aparece la palabra buscada

Es imprescindible que en el fichero de resultados no aparezcan mezcladas las apariciones de palabras en los distintos ficheros. Es decir, los hilos tienen que acceder de manera síncrona al archivo de log, y escribir de uno en uno en el mismo.

Tengo el código entero generado para hacer todo lo que pide. Para el acceso síncrono al archivo de texto tengo creada una clase que es la encargada del manejo del txt en el que guardo el log.

Código:
public class FileAccess {
	
	private static FileWriter log;
	private static PrintWriter pw;
	
	public FileAccess(FileWriter log){
		setLog(log);		
		setPw(new PrintWriter(log));
	}
	
	//Synchronized access
	public synchronized void printLine(String line){
		getPw().println(line);
		getPw().close();
		
	}
}
Los hilos los lanzo en un bucle dentro del programa principal (la clase WordSearcher es la que es thread)

Código:
private void launchThreads(){
		numOfThreads = txtFiles.length;
		wordSearcherList = new WordSearcher[txtFiles.length];
		for (int i=0; i<txtFiles.length;i++) {
			wordSearcherList[i] = new WordSearcher(getWord(), txtFiles[i], logPath, logFile, logFW, sem, numOfThreads, imDone);
			wordSearcherList[i].start();
		}		
	}
Y luego los espero desde el programa principal también en bucle:
Código:
private void joinThreads(){
		for (int i=0; i<wordSearcherList.length;i++){
			try {
				wordSearcherList[i].join();
			} catch (InterruptedException e) {
				System.err.println("Problems waiting threads");
			}
		}
				
	}
Estoy haciendo las pruebas con tres txt, todos con la palabra "servicios" y dos de ellos con la palabra "adios". Tanto con la primera palabra como con la segunda, parece que no espera a los hilos el programa principal. Unas veces me imprime las coincidencias en uno de los archivos sólo, otras en dos, otras en los tres...

He depurado y si que hace bien la búsqueda en cada hilo, y entra en aquellos en los que tiene que dejar constancia en el log para escribir, aunque no siempre lo modifica.

¿Cómo puedo hacer la escritura en el archivo de log de manera que el resultado final contenga lo que ha encontrado en todos los hilos?

Adjunto el trozo de código de WordSearcher en el que hago la escritura en el log:

Código:
FileAccess fa = new FileAccess(logFW);
fa.printLine(toPrint);
Si necesitáis saber algo más del código decidme, y a ver si alguien sabe ayudarme a conseguir una sincronización de verdad. Creo que el fallo está en cuando accedo a escribir el log, puede que incluso en la creación del fichero.

Gracias de antemano, un saludo
  #2 (permalink)  
Antiguo 09/10/2014, 06:36
Avatar de chuidiang
Colaborador
 
Fecha de Ingreso: octubre-2004
Mensajes: 3.774
Antigüedad: 19 años, 9 meses
Puntos: 454
Respuesta: Sincronizacion hilos - Escritura txt

Hola:

Asegúrate de cerrar el fichero antes de que el programa principal trate de mostrarlo en consola. PrintWriter tiene un buffer y no se garantiza la escritura real en disco hasta que o bien cierras el fichero, o bien lo creas con autoFlush a true en el constructor http://docs.oracle.com/javase/7/docs...intWriter.html

Se bueno.
__________________
Apuntes Java
Wiki de Programación
  #3 (permalink)  
Antiguo 09/10/2014, 09:23
Avatar de calathea  
Fecha de Ingreso: octubre-2008
Ubicación: Valladolid
Mensajes: 122
Antigüedad: 15 años, 9 meses
Puntos: 3
Respuesta: Sincronizacion hilos - Escritura txt

No me termina de funcionar añadiendo el true al constructor. Le daré unas vuetas a lo que me has pasado y probaré a ver si es que se me ha pasado algo. Sino volveré a preguntar. Gracias.
  #4 (permalink)  
Antiguo 09/10/2014, 11:27
Avatar de farfamorA  
Fecha de Ingreso: noviembre-2010
Ubicación: Lima
Mensajes: 136
Antigüedad: 13 años, 8 meses
Puntos: 24
Respuesta: Sincronizacion hilos - Escritura txt

Escribir concurremente desde varios hilos a un fichero de texto... hmm.
Y qué tal si cada hilo escribe su propio archivo de texto (temporal) y luego lanzas un proceso más, el de juntar esos archivos en uno sólo y eliminar los temporales.
  #5 (permalink)  
Antiguo 09/10/2014, 12:35
Avatar de calathea  
Fecha de Ingreso: octubre-2008
Ubicación: Valladolid
Mensajes: 122
Antigüedad: 15 años, 9 meses
Puntos: 3
Respuesta: Sincronizacion hilos - Escritura txt

No me sirve farfamorA, tengo que hacerlo de esa manera. Es posible, otras veces he hecho cosas parecidas, simplemente es cuestión de sincronizar el acceso...lo único que esta vez se me ha atascado. Como digo, probare la solución de chuidiang a fondo y a ver que pasa. Gracias.
  #6 (permalink)  
Antiguo 09/10/2014, 14:47
Avatar de chuidiang
Colaborador
 
Fecha de Ingreso: octubre-2004
Mensajes: 3.774
Antigüedad: 19 años, 9 meses
Puntos: 454
Respuesta: Sincronizacion hilos - Escritura txt

Hola:

No sé qué problema tienes. ¿Sale todo en el fichero pero sale entremezclado? ¿o no sale completo?

El tema de sincronización a falta de ver más código, lo veo raro. Si cada hilo hace su propio new de FileAccess, tienes una instancia de esa clase por cada hilo. El método synchronized afecta a una instancia concreta, por lo que si cada hilo tiene su propia instancia, nunca va a haber dos hilos accediendo a la misma instancia, por lo que es indistinto que pongas el método synchronized o no, y tampoco estás sincronizando el acceso al fichero.

Como dentro de FileAcess has puesto static el PrintWriter, cuando haces new FileAccess(logFW), estás creando tres PrintWriter (cada FileAccess hace un new PrintWriter) que están "machacandose" mutuamente, ya que los guardas en el atributo que es static. Al final, el único PrintWriter válido es el del último hilo que haya hecho el new. Puedes tener problemas si antes de "machacar", el hilo anterior ha empezado a escribir en el PrintWriter anterior a través del fileAccess.printLine()

Yo en tu lugar haría lo siguiente. En vez de pasar logFW a los hilos, pásales directamente un PrintWriter (el mismo a todos). Cuando quieras que un hilo escriba, haz esto

Código Java:
Ver original
  1. synchronized (elPrintWriter) {
  2.    elPrintWriter.println(lo que sea);
  3. }

y en el código principal, cuando salgas del bucle de los join, cierra el PrintWriter para asegurar la escritura del ficheoro en disco. Luego lo muestras.

Se bueno.
__________________
Apuntes Java
Wiki de Programación
  #7 (permalink)  
Antiguo 09/10/2014, 16:25
Avatar de calathea  
Fecha de Ingreso: octubre-2008
Ubicación: Valladolid
Mensajes: 122
Antigüedad: 15 años, 9 meses
Puntos: 3
Respuesta: Sincronizacion hilos - Escritura txt

Sabía que tenía q ser una estupidez!!! Mil gracias chuidiang!! Si no me llegas a comentar lo del static ni me doy cuenta.

Todo se reducía a quitar el atributo static...y para asegurar he creado el PrintWriter con autoFlush a true...y lo he cerrado en el principal tras el join. Además he prescindido de la clase FileAccess, por simplificarlo todo: la función de escritura la he reducido a lo que tu me has indicado, que es más que suficiente. Ahora va como la seda!

El problema era el que comentabas: los hilos estaban machacando la escritura de los anteriores en el fichero de log (aunque curiosamente esto no ocurría siempre...a veces quedaba el log de dos hilos de los tres...o de todos incluso si había suerte!).

Gracias de nuevo!

Etiquetas: clase, escritura, hilos, programa, sincronizacion, txt
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 15:38.