Ver Mensaje Individual
  #1 (permalink)  
Antiguo 30/11/2015, 17:52
inazense
Invitado
 
Mensajes: n/a
Puntos:
Pregunta Error sincronizando procesos

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 original
  1. package ej3;
  2.  
  3. public class Cuenta {
  4.  
  5.     // Propiedades
  6.     private int numClientes = 0;
  7.     private boolean validarOperacion = false; // Valido la operacion y eliminar al cliente en clase Banco
  8.     private int turnoCliente = 1;
  9.     private int saldoActual;
  10.     private int saldoMaximo; // ¿Por qué un saldo máximo? Me haría ilusión que no me limiten el dinero que pueda tener...
  11.     private int estadoCuenta = -1;
  12.     private Persona ultimoCliente;
  13.    
  14.     // Constructor
  15.     public Cuenta(int saldoActual, int saldoMaximo){
  16.         this.saldoActual = saldoActual;
  17.         this.saldoMaximo = saldoMaximo;
  18.     }
  19.    
  20.     // Métodos
  21.     public void setNumClientes(int x){
  22.         this.numClientes = x;
  23.     }
  24.    
  25.     public int getEstadoCuenta(){
  26.         return estadoCuenta;
  27.     }
  28.    
  29.     public synchronized void ingresar(int cantidad, int turno, Persona ultimoCliente){
  30.         /* Codigos de resultado:
  31.          *  -1 = No es su turno
  32.          *  -2 = saldoMaximo excedido
  33.          *  otra cantidad = ingreso correcto
  34.          */
  35.        
  36.         while (validarOperacion == false || turnoCliente != turno){
  37.             try{
  38.                 wait();
  39.             }
  40.             catch(InterruptedException e){}
  41.         } // Fin de while
  42.         if (turno == turnoCliente){
  43.             if (saldoActual + cantidad <= saldoMaximo){
  44.                 saldoActual = saldoActual + cantidad;
  45.                 estadoCuenta = cantidad;
  46.                 System.out.println(ultimoCliente.getNombre() + " ha ingresado " + cantidad + " euros");
  47.             }
  48.             else{
  49.                 estadoCuenta= -2;
  50.             }
  51.             this.ultimoCliente = ultimoCliente;
  52.             validarOperacion = false; // Disponible para validar clientes
  53.             if (turnoCliente == numClientes)
  54.                 turnoCliente = 1;
  55.             else
  56.                 turnoCliente++;
  57.         } // Fin de if
  58.         notifyAll();
  59.     } // Fin ingresar
  60.    
  61.     public synchronized void retirar(int cantidad, int turno, Persona ultimoCliente){
  62.         while (validarOperacion == false || turnoCliente != turno){
  63.             try{
  64.                 wait();
  65.             }
  66.             catch(InterruptedException e){}
  67.         } // Fin de while
  68.         if (turno == turnoCliente){
  69.             if (saldoActual - cantidad >= 0){
  70.                 saldoActual = saldoActual - cantidad;
  71.                 estadoCuenta = cantidad;
  72.                 System.out.println(ultimoCliente.getNombre() + " ha retirado " + cantidad + " euros");
  73.             }
  74.             else{
  75.                 estadoCuenta = -2;
  76.             }
  77.             this.ultimoCliente = ultimoCliente;
  78.             validarOperacion = false; // Disponible para validar clientes
  79.             if (turnoCliente == numClientes)
  80.                 turnoCliente = 1;
  81.             else
  82.                 turnoCliente++;
  83.         } // Fin de if
  84.         notifyAll();
  85.     } // Fin retirar
  86.    
  87.     // Si el usuario ha hecho una operacion incorrecta, este método lo expulsa desde Clase Banco
  88.     @SuppressWarnings("deprecation")
  89.     public synchronized void validarUsuario(){
  90.         while (validarOperacion == true){
  91.             try{
  92.                 wait();
  93.             }
  94.             catch(InterruptedException e){}
  95.         } // Fin de while
  96.         if (this.estadoCuenta == -2){
  97.             ultimoCliente.stop();
  98.             System.out.println("El cliente" + ultimoCliente.getNombre() + " ha sido sacado del sistema");
  99.         }
  100.         validarOperacion = true;
  101.         notifyAll();
  102.     }
  103. }

Clase Persona
Código Java:
Ver original
  1. package ej3;
  2.  
  3. public class Persona extends Thread{
  4.  
  5.     // Propiedades
  6.     private String nombre;
  7.     private int numCliente;
  8.     private Cuenta cuenta;
  9.    
  10.     // Constructor
  11.     public Persona(String nombre, int numCliente){
  12.         this.nombre = nombre;
  13.         this.numCliente = numCliente;
  14.     }
  15.    
  16.     // Métodos
  17.     public void run(){
  18.         while(true){
  19.             cuenta.ingresar(generarCifra(), numCliente, this);
  20.             try{
  21.                 sleep(300);
  22.             }
  23.             catch(InterruptedException e){}
  24.            
  25.             cuenta.retirar(generarCifra(), numCliente, this);
  26.             try{
  27.                 sleep(300);
  28.             }
  29.             catch(InterruptedException e){}
  30.         } // Fin while
  31.     } // Fin run
  32.    
  33.     public int generarCifra(){
  34.         return (int) (Math.random()*500+1);
  35.     }
  36.    
  37.     public String getNombre(){
  38.         return nombre;
  39.     }
  40. }

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 original
  1. package ej3;
  2.  
  3. public class Banco extends Thread{
  4.  
  5.     // Propiedades
  6.     private Cuenta cuenta;
  7.  
  8.     // Constructor
  9.     public Banco(Cuenta cuenta){
  10.         this.cuenta = cuenta;
  11.     }
  12.    
  13.     // Métodos
  14.     public void run(){
  15.         while (true){
  16.             cuenta.validarUsuario();
  17.         }
  18.     } // Fin de run
  19. }

Main
Código Java:
Ver original
  1. package ej3;
  2. import java.util.Vector;
  3. public class Main {
  4.  
  5.     public static void main(String[] args) {
  6.         Cuenta cuenta = new Cuenta(2000, 10000);
  7.         Vector<Persona> gente = new Vector<Persona>();
  8.         Banco banco = new Banco(cuenta);
  9.         gente.addElement(new Persona("Inazio", 1));
  10.         gente.addElement(new Persona("Paula", 2));
  11.         gente.addElement(new Persona("Ana", 3));
  12.         gente.addElement(new Persona("Edu", 4));
  13.        
  14.         cuenta.setNumClientes(gente.size());
  15.         banco.start();
  16.         for (int i = 0; i < gente.size(); i++){
  17.             gente.elementAt(i).start();
  18.         }
  19.     }
  20. }