Buscar
Social
Ofertas laborales ES

Foro sobre Java SE > Comportamiento extraño en multithread

Hola.

He estado un buen tiempo enfrentandome a un comportamiento no esperado en una pequeña utilidad de backup que he realizado.

Solicito su colaboración para identificar el error por que no lo veo. (y de una vez ayudarme comprender un concepto que seguro manejo equivocadamente).


Tengo una clase principal que activa hilos para buscar en una base de datos la siguiente tarea.

El hilo principal tiene por intención maximizar la velocidad de lectura (que hasta el momento es motivado a muchas variables el cuello de botella).

Luego de leer el binario gestiona un thread para su inserción en base de datos (y volver a la lectura cuanto antes.


/*************************************************/
// Clase que inserta
public class ThreadInserting implements Runnable{

private DbContainer dbc;
private ImageBackup Backup;

public ThreadInserting(DbContainer dBc,ImageBackup Backup) {
this.dbc=dBc;
this.Backup=Backup;
}

@Override
public void run() {
//System.out.println("Insertando: "+this.Backup.getId());
this.dbc.insertarBackup(this.Backup);
Backup.getReference().reduceThreadsInserting();
}
}
/*************************************************/

/*************************************************/
// Clase que busca tareas
public class ThreadSearchingNextTask implements Runnable {

private boolean finalizado;
private TaskBackup task;
private DbContainer dbc;

public ThreadSearchingNextTask(DbContainer dBc) {
this.finalizado = false;
this.dbc = dBc;
this.task=null;
}

@Override
public void run() {
this.task = this.dbc.getNextTaskBackup();
this.finalizado = true;
}

//getters
}
/*************************************************/

/*************************************************/
// Clase con los metodos hacia la base de datos
public class DbContainer {

private Connection conDB = null;
private ResultSet task = null;
private boolean ultimaEntregada;

//El constructor hace la conexión y genera el resultset de tareas


synchronized public TaskBackup getNextTaskBackup() {
TaskBackup result = null;
if(this.ultimaEntregada) {
return null;
}
try {
result = new TaskBackup(task.getInt(1), task.getInt(2), task.getInt(3), task.getString(4));
if (!task.next()) {
result.setUltima();
this.ultimaEntregada=true;
}
} catch (SQLException ex) {
Logger.getLogger(DbContainer.class.getName()).log(Level.SEVERE, null, ex);
}
//System.out.println("Entregando: "+result.getId());
return result;
}

synchronized public void insertarBackup(ImageBackup Backup) {
String sql = "INSERT INTO backup VALUES(?,?)";
try {
PreparedStatement stmt = this.conDB.prepareStatement(sql);
stmt.setInt(1, Backup.getId());
stmt.setBytes(2, Backup.get());
stmt.executeUpdate();
stmt.close();
} catch (SQLException ex) {
Logger.getLogger(DbContainer.class.getName()).log(Level.SEVERE, null, ex);
}
sql = "update task set proccesed=1 where ID=?";
try {
PreparedStatement stmt = this.conDB.prepareStatement(sql);
stmt.setInt(1, Backup.getId());
stmt.executeUpdate();
stmt.close();
} catch (SQLException ex) {
Logger.getLogger(DbContainer.class.getName()).log(Level.SEVERE, null, ex);
}

}

}
/*************************************************/


/*************************************************************************************************/
// extracto de la clase main
// primer listado
ThreadSearchingNextTask buscador = new ThreadSearchingNextTask(dbcontainer);
new Thread(buscador).start();
ThreadSearchingNextTask buscador_trabajo=null;
TaskBackup next_image=null;

do {

// GETTING WORK

// me quedo con el temporal para este ciclo
buscador_trabajo = null;
buscador_trabajo = buscador;

// lanzo el hilo para buscar el siguiente
buscador = new ThreadSearchingNextTask(dbcontainer);
new Thread(buscador).start();

if (!buscador_trabajo.isFinished()) {
while (!buscador_trabajo.isFinished()) {
Thread.sleep(100);
if (task_finished != 0) {
this.addBusquedasRetrasadas();
}
}
}
next_image = null;
next_image = buscador_trabajo.getTaskBackup();
//System.out.println(next_image.toString());


// la lectura
byte[] image=null;
try {
File f = new File(next_image.getPath());
FileInputStream in = new FileInputStream(f);
image = new byte[(int) f.length()];
in.read(image);
} catch (IOException e) {
System.out.print(e.getMessage());
}

ImageBackup backup=new ImageBackup(next_image.getId(),image);


// la insercion
ThreadInserting agente_respaldo= new ThreadInserting(dbcontainer,backup);
new Thread(agente_respaldo).start();
this.addThreadsInserting();

task_finished++;

// log
if (task_finished%1==10) {
System.out.println("Tareas; " + task_finished + " Retrasos: "+this.getBusquedasRetrasadas()+" Insertando: "+this.getThreadsInserting());
}

//System.out.println("se termino la tarea "+next_image.getId());


} while (task_finished < 51 && !next_image.isUltima());
/*************************************************************************************************/

diciembre 26, 2011 | Unregistered Commenterjzambrano

Se me olvido mencionar el comportamiento de la falla.

Lo estoy probando con 10 tareas.

Si lo corro en debug me hace las 10 bien y se comporta según lo esperado.
Si lo corro exacto me realiza 9 tareas no las 10 típicamente entre las dos últimas.

diciembre 26, 2011 | Unregistered Commenterjzambrano

Faltan algunas clases, por lo que no es posible realizar pruebas.

diciembre 27, 2011 | Registered Commenterchoces