Tengo un ejercicio en el que debo crear un objeto Cuenta en el que varios objetos Persona puedan sacar y retirar dinero, y si intenta ingresar más dinero del limite maximo o dejar la cuenta en negativo, deberá finalizar el proceso persona que lo esté haciendo.
Los métodos ingresar y retirar de Cuenta deben estar sincronizados, y la clase Persona en run(), ya que debe descender de Thread, tendrá que hacer un ingreso, una retirada y alternarlos con algún sleep.
Mi problema surge a la hora de hacer la llamada desde Persona a Cuenta para ingresar dinero. Aparece el siguiente error:
Exception in thread "Thread-1" Exception in thread "Thread-4" Exception in thread "Thread-2" Exception in thread "Thread-3" java.lang.NullPointerException
at ej3.Persona.run(Persona.java:19)
java.lang.NullPointerException
at ej3.Persona.run(Persona.java:19)
java.lang.NullPointerException
at ej3.Persona.run(Persona.java:19)
java.lang.NullPointerException
at ej3.Persona.run(Persona.java:19)
No entiendo porque me sale. ¿Me podéis ayudar a comprender el fallo?
El código de todas las clases es el siguiente:
Clase Cuenta
Código Java:
Ver originalpackage ej3;
public class Cuenta {
// Propiedades
private int numClientes = 0;
private boolean validarOperacion = false; // Valido la operacion y eliminar al cliente en clase Banco
private int turnoCliente = 1;
private int saldoActual;
private int saldoMaximo; // ¿Por qué un saldo máximo? Me haría ilusión que no me limiten el dinero que pueda tener...
private int estadoCuenta = -1;
private Persona ultimoCliente;
// Constructor
public Cuenta(int saldoActual, int saldoMaximo){
this.saldoActual = saldoActual;
this.saldoMaximo = saldoMaximo;
}
// Métodos
public void setNumClientes(int x){
this.numClientes = x;
}
public int getEstadoCuenta(){
return estadoCuenta;
}
public synchronized void ingresar(int cantidad, int turno, Persona ultimoCliente){
/* Codigos de resultado:
* -1 = No es su turno
* -2 = saldoMaximo excedido
* otra cantidad = ingreso correcto
*/
while (validarOperacion == false || turnoCliente != turno){
try{
wait();
}
} // Fin de while
if (turno == turnoCliente){
if (saldoActual + cantidad <= saldoMaximo){
saldoActual = saldoActual + cantidad;
estadoCuenta = cantidad;
System.
out.
println(ultimoCliente.
getNombre() + " ha ingresado " + cantidad
+ " euros"); }
else{
estadoCuenta= -2;
}
this.ultimoCliente = ultimoCliente;
validarOperacion = false; // Disponible para validar clientes
if (turnoCliente == numClientes)
turnoCliente = 1;
else
turnoCliente++;
} // Fin de if
notifyAll();
} // Fin ingresar
public synchronized void retirar(int cantidad, int turno, Persona ultimoCliente){
while (validarOperacion == false || turnoCliente != turno){
try{
wait();
}
} // Fin de while
if (turno == turnoCliente){
if (saldoActual - cantidad >= 0){
saldoActual = saldoActual - cantidad;
estadoCuenta = cantidad;
System.
out.
println(ultimoCliente.
getNombre() + " ha retirado " + cantidad
+ " euros"); }
else{
estadoCuenta = -2;
}
this.ultimoCliente = ultimoCliente;
validarOperacion = false; // Disponible para validar clientes
if (turnoCliente == numClientes)
turnoCliente = 1;
else
turnoCliente++;
} // Fin de if
notifyAll();
} // Fin retirar
// Si el usuario ha hecho una operacion incorrecta, este método lo expulsa desde Clase Banco
@SuppressWarnings("deprecation")
public synchronized void validarUsuario(){
while (validarOperacion == true){
try{
wait();
}
} // Fin de while
if (this.estadoCuenta == -2){
ultimoCliente.stop();
System.
out.
println("El cliente" + ultimoCliente.
getNombre() + " ha sido sacado del sistema"); }
validarOperacion = true;
notifyAll();
}
}
Clase Persona
Código Java:
Ver originalpackage ej3;
public class Persona
extends Thread{
// Propiedades
private int numCliente;
private Cuenta cuenta;
// Constructor
public Persona
(String nombre,
int numCliente
){ this.nombre = nombre;
this.numCliente = numCliente;
}
// Métodos
public void run(){
while(true){
cuenta.ingresar(generarCifra(), numCliente, this);
try{
sleep(300);
}
cuenta.retirar(generarCifra(), numCliente, this);
try{
sleep(300);
}
} // Fin while
} // Fin run
public int generarCifra(){
return (int) (Math.
random()*500+1); }
return nombre;
}
}
Clase Banco (la uso para alternar las clases persona y matar los hilos si se exceden al retirar o ingresar dinero
Código Java:
Ver originalpackage ej3;
public class Banco
extends Thread{
// Propiedades
private Cuenta cuenta;
// Constructor
public Banco(Cuenta cuenta){
this.cuenta = cuenta;
}
// Métodos
public void run(){
while (true){
cuenta.validarUsuario();
}
} // Fin de run
}
Main
Código Java:
Ver originalpackage ej3;
import java.util.Vector;
public class Main {
public static void main
(String[] args
) { Cuenta cuenta = new Cuenta(2000, 10000);
Vector<Persona> gente = new Vector<Persona>();
Banco banco = new Banco(cuenta);
gente.addElement(new Persona("Inazio", 1));
gente.addElement(new Persona("Paula", 2));
gente.addElement(new Persona("Ana", 3));
gente.addElement(new Persona("Edu", 4));
cuenta.setNumClientes(gente.size());
banco.start();
for (int i = 0; i < gente.size(); i++){
gente.elementAt(i).start();
}
}
}