Newsgroup: it.comp.java
Titolo: [Help!] StackOverflowError

Salve a tutti del gruppo!
Premetto innanzitutto che sono ancora molto inesperto.
All'università ci hanno dato un progetto da scrivere in Java che simula
un supermercato. L'obiettivo (nel mio caso) è trovare la lunghezza media
e max delle code che si formano a seconda del numero delle casse e dei
tempi di servizio e arrivo dei clienti.
Praticamente da un Heap estraggo ogni volta un evento che può essere
l'arrivo o l'uscita di un cliente.
Il problema è che io l'ho implementato, e credo che almeno
strutturalmente possa essere corretto, ma non riesco a capire perchè ogni
volta che lo eseguo esce quasi subito:
Exception in thread "main" java.lang.StackOverflowError
E osservo che vengono eseguite nel main al max una trentina di iterazioni
(quando devo invece fornire i risultati di 100000!). Da cosa può essere
dato? Io non so proprio più cosa guardare. So che questo problema è
normalmente relativo alla ricorsione, ma io non ho una linea di
ricorsione nel mio progetto! Le strutture dati credo siano corrette (le
ho testate) e sono l'Heap e le Queue fondamentalmente.
Ho letto pure il thread poco sotto ma non credo che possa aiutarmi.
Vi allego i due files fondamentali, quello col main (Simulazione) e
quello con il Supermercato. Mi scuso subito per la lunghezza del post, ma
ho davvero bisogno di aiuto.
Grazie da ora!
Ecco il file col main:
public class Simulatore{
    public static void main(String[] args){
	for(int i=0; i < args.length; i++)
	    if(getInt(args[i]) <= 0){
		System.out.println("INSERIRE SOLO VALORI INTERI MAGGIORI DI 0!");
		return;
	    }
 
	try{
	    Market m = new Market( getInt(args[0]), getInt(args[1]), getInt(args[2]) );	 
	    int k = getInt(args[3]);
 
	    for(int i = 0; i<k; i++){
		m.extractNewEvent();
		System.out.println(i);
	    }
 
	    m.getFinalStats();
	}
 	catch(IllegalParameterInMarket e){System.out.println(e);}
    }
 
    public static int getInt(String s){
 
	return Integer.parseInt(s);
    }
}
//--------------------------------------------------------------
E ora ecco quello più grosso quello che implementa il Market che si vede
sopra:
import java.lang.Integer;
import java.util.Random;
public class Market{
    private LQueue[] cashDesks; //Queste sono le casse dove si accodano i clienti
    private Random rand;//random seed
    private int T; //tempo simulato
    final int m_serv;
    final int m_arr;
    final int N;
    private HeapPriorityQueue Q;
    private Statistics S;
    /*SOTTOCLASSE STATISTICS*/
    protected class Statistics{
	private int numClients; //memorizza il numero totale di clienti generati
	private	int maxQueueLength;//memorizza la lunghezza massima della fila	
	private long totalExitClients;//memorizza tutti i clienti usciti dalle casse
	private long totalWaitTime;//memorizza la somma totale dei tempi di attesa (serve per la media)
	private long queueLengthsSum;//memorizza la somma delle lunghezze delle code viste dai clienti (serve per la media)
 
	protected Statistics(){
 
	    numClients = 0;
	    maxQueueLength = 0;
	    queueLengthsSum = 0;
	    totalExitClients = 0;
	    totalWaitTime = 0;
	}
 
	/*Metodo che aggiorna il numero totale dei clienti creati*/
	protected void newClient(){
	    numClients++;
	}
	/*Ritorna il totale dei clienti*/
	protected int getNumClients(){
	    return numClients;
	}
 
	/*Aggiorna il numero dei clienti usciti*/
	protected void clientExit(){
	    totalExitClients++;
	}
 
 
	/*Questo metodo memorizza le statistiche temporali al momento in cui il cliente va in cassa*/
	protected void clientAtCashdeskTime(Client c){
	    totalWaitTime += c.timeInQueue();
	}
 
	/*Questo metodo memorizza le statistiche sulla coda al momento in cui il cliente va in cassa*/
	protected void clientAtCashdeskQueue(Client c){
	    if(c.myQueueStatus() > maxQueueLength)
		maxQueueLength = c.myQueueStatus();
 
	    queueLengthsSum += c.myQueueStatus();
	}
	/*ritorna la lunghezza media delle code alle casse*/
	protected double averageQueueLength(){
 
	    return (queueLengthsSum/numClients);
	}
 
 
	/*ritorna la massima lunghezza raggiunta dalle code*/
	protected long maxQueueLength(){
	    return maxQueueLength;
	}
	/*ritorna il tempo medio di attesa in coda (valido naturalmente solo per i clienti usciti)*/
	protected double averageWaitingTimeInQueue(){
 
	    return (totalWaitTime/totalExitClients);
	}
    }
    //----------------------------------------------------
    //Constructors
    public Market(int n, int m_ar, int m_ser) throws IllegalParameterInMarket{
 
	if( (n <= 0) || (m_ser <= 0) || (m_ar <= 0))
	    throw new IllegalParameterInMarket();
 
 
	N = n;
	m_arr = m_ar;
	m_serv = m_ser;
	S = new Statistics();
 
	try{
	    Q = new HeapPriorityQueue();
	    Q.insert(new Integer(0), new Event());//Inseriamo nella coda l'arrivo del primo cliente
	}
	catch(InvalidKeyException e){
	    System.out.println("ERROR(Market constructor): "+e);
	}
 
	T = 0 ;
	rand = new Random();
	cashDesks = new LQueue[N];
 
	for(int z=0; z<N; z++){//inizializzazione delle code
	    cashDesks[z] = new LQueue();
	}
    }
 
    //default methods
 
    /*Questo metodo ha lo scopo di estrarre dalla coda con priorità i nuovi eventi e quindi
      gestire le conseguenze della estrazione*/
    public void extractNewEvent(){
	try{
	    Entry newEvent = Q.removeMin();
	if( ((Event)newEvent.value()).type() == 'A')//arrivo di un nuovo cliente: si lancia il metodo clientArrival
	    clientArrival( ((Integer)newEvent.key()).intValue() );//passato il parametro del tempo di uscita
 
	else //il cliente deve uscire dalla coda
	    clientExit( ((Integer)newEvent.key()).intValue(), ((Event)newEvent.value()).rankQueue() );
	//nell'istruzione sopra, passo al metodo clientExit il tempo di uscita del cliente e la coda da cui esce
 
	}
	catch(EmptyPriorityQueueException e){
	    System.out.println("ERROR(Market.extractNewEvent()): "+e);
	}
    }
 
 
    /*Questo metodo gestisce l'arrivo di un cliente e relative conseguenze*/    
    public void clientArrival(int time){
 
	T = time;//reimpostiamo il tempo simulato
 
	int minSize = cashDesks[0].size();//trova la coda più corta
	int r = 0;
	for(int i = 1; i < cashDesks.length; i++)
	    if(cashDesks[i].size() < minSize){
		minSize = cashDesks[i].size(); 
		r = i;
	    }
	Client c = new Client(time, minSize);//crea il nuovo cliente(che ricorderà il tempo di messa in coda e la lunghezza della stessa)	
	S.newClient();//Aggiorniamo il totale
	try{
	    if(minSize == 0){//se la cassa è vuota
		cashDesks[r].enqueue(c);//il cliente va in coda ma...
 
		int exit = newServTime();//...viene servito subito (generato il tempo di servizio)
		Q.insert(new Integer(T+exit), new Event(r));//inserito l'evento uscita
	    }
 
	    else//la cassa ha una coda non nulla
		cashDesks[r].enqueue(c);//il cliente viene messo in coda
 
 
	    int arr = newArrivTime(); 	//genero l'arrivo del prossimo cliente
	    Q.insert(new Integer(T + arr), new Event());
	}
	catch(InvalidKeyException e){
	    System.out.println("ERROR(Market.clientArrival(int time)) - " +e);
	}
    }
 
 
    public void clientExit(int time, int rankQueue){//gestisce l'uscita di un cliente e le relative conseguenze
	try{
	    T = time;//reimpostiamo il tempo simulato
 
	    Client c = (Client)cashDesks[rankQueue].dequeue();//"salviamo" il cliente uscito
	    S.clientExit();
 
 
	    if( !(cashDesks[rankQueue].isEmpty()) ){//verifichiamo ora se ci sono altri clienti in coda
		( (Client)cashDesks[rankQueue].front() ).setTimeInQueue(time);//aggiorniamo i dati del nuovo cliente in cassa
		//Raccolgo ora le statistiche
		S.clientAtCashdeskTime( (Client)cashDesks[rankQueue].front() );
		S.clientAtCashdeskQueue( (Client)cashDesks[rankQueue].front() );
		//Impostiamo ora l'uscita di questo cliente
		int exit = newServTime();
		Q.insert(new Integer(T + exit), new Event(rankQueue));//ecco il suo evento uscita
	    }
	}
	catch(EmptyQueueException e){
	    System.out.println(e);
	}
	catch(InvalidKeyException e){
	    System.out.println(e);
	}
    }
 
 
    /*genera un nuovo tempo di servizio*/
    public int newServTime(){
 
	return rand.nextInt(2*m_serv+1);
    }
    /*genera un nuovo tempo di arrivo*/
    public int newArrivTime(){
 
	return rand.nextInt(2*m_arr+1);
    }
 
 
    /*metodo ausiliario che serve per le statistiche finali.
      Permette di considerare i dati sulla lunghezza delle code anche dei clienti che ancora
      non sono arrivati alla cassa.
      ATTENZIONE: Questo metodo va eseguito solo con getFinalStats() alla fine della simulazione,
      visto che va a svuotare le code.
    */
    public void flush(){
	try{
	    for(int i=0; i<N; i++){
		if(!(cashDesks[i].isEmpty()))
		    cashDesks[i].dequeue();//"Gettiamo" questo cliente. Le sue statistiche sono già state raccolte prima
 
		while( !(cashDesks[i].isEmpty()) )//Se ci sono ancora clienti...
		    S.clientAtCashdeskQueue( (Client)cashDesks[i].dequeue() );//...raccogliamo queste ultime statistiche sulle code
	    }
	}
	catch(EmptyQueueException e){
	    System.out.println(e);
	}
    }
    /*Stampa sullo Standard Output le statistiche*/
    public void getFinalStats(){
	flush(); //Svuotiamo le code per gli ultimi dati
	//Diamo ora in output i risultati
	System.out.println("Clienti totali: " + S.getNumClients());
	System.out.println("La lunghezza media della fila incontrata dai clienti arrivati è: " + S.averageQueueLength());
	System.out.println("La lunghezza massima della fila incontrata dai clienti arrivati è: " + S.maxQueueLength());
	System.out.println("\n\n\nDATO NON RICHIESTO NEL PROGETTO (riportato comunque)");
	System.out.println("Il tempo medio di attesa dei clienti in fila é: " + S.averageWaitingTimeInQueue());
    }
}
-- 
Qualsiasi idiota è capace di prendere una tigre per i
coglioni, ma ci vuole un eroe per continuare a stringere.
Geometra Meneghetti (Enrico Bertolino)

On Fri, 05 Mar 2004 23:36:24 +0100, Jon wrote:
Ho risolto!!!! YAHOOOOOOOOOOOOOOOOO!
Colpa di un errorino nascosto (ma davvero nascosto) in un'altra classe.
Grazie cmq. 
