Di nuovo sui Thread

di il
16 risposte

Di nuovo sui Thread

Facciamo una premessa e ditemi se dico stupidaggini:
sleep , mette in pausa il thread e NON rilascia la risorsa ad altri thread
wait , mette in pausa il thread, MA rilasia la risorsa ad altri thread
notify , notifica ad UN SOLO thread che sta in pausa che la risorsa è libera
notifyAll, notifica a TUTTI i thread che stanno in pausa che la risorsa è libera.

Se questo è corretto, volevo realizzare questo esercizio (quello vecchio degli aerei-Thread che atterrano sulla Pista-Risorsa, funziona correttamente).
Ora, sulla base di quell'esercizio:
- crea 10 Aereo/Thread
- usa la risorsa Pista per atterrare, attende con sleep X secondi con random
- termina il suo ciclo vitale e un altro Thread usa la stessa risorsa "PISTA"

Volevo fare il contrario con 3 piste e 10 aerei, decollo:
- creo 10 Aerei/Thread
- chiamo un metodo controlliPrevolo() della TorreDiControllo che impiegano X secondi e aspettano OK dalla torre, i controlli possono essere fatti in simultanea, quindi se ho capito bene in questo metodo uso wait()
- terminata questa fase, chiamo il metodo decolla()

....qui il problema. come faccio ad far usare al Thread la risorsa Pista? Ne ho tre diverse, dovrei controllare se sono libere.

Volevo procedere in questo modo. Ai primi 3 Thread, assegno una pista a testa, nel metodo decolla() ci sarà il sleep(Y secondi), ma poi per gli altri sette, dovrei chiamare il metodo notifyAll() e come faccio a capire quale Pista chiamare?

Il quarto Thread quale metodo decolla() di quale oggetto deve chiamare? come faccio a farglielo capire?
Questa parte dei thread non l'ho trovata su internet.

NOn so se mi sono spiegato.
Grazie.
Tagan

16 Risposte

  • Re: Di nuovo sui Thread

    tagan ha scritto:


    sleep , mette in pausa il thread e NON rilascia la risorsa ad altri thread
    Corretto, sleep NON rilascia alcun lock.

    tagan ha scritto:


    wait , mette in pausa il thread, MA rilasia la risorsa ad altri thread
    Corretto, wait rilascia il lock dell'oggetto (su cui il wait è stato invocato possedendo il lock di quel oggetto)

    tagan ha scritto:


    notify , notifica ad UN SOLO thread che sta in pausa che la risorsa è libera
    notifyAll, notifica a TUTTI i thread che stanno in pausa che la risorsa è libera.
    Corretto. Precisazione però: tutti i thread ma solo quelli che sono nel wait set di QUEL oggetto specifico. Ovviamente ... non "tutti tutti" in generale.
    Nota che il notify() "singolo" notifica un solo thread MA scelto "a caso" (cioè non c'è una logica specifica dietro).

    tagan ha scritto:


    - chiamo un metodo controlliPrevolo() della TorreDiControllo che impiegano X secondi e aspettano OK dalla torre, i controlli possono essere fatti in simultanea, quindi se ho capito bene in questo metodo uso wait()
    Qui la questione si può vedere in altro modo: se hai un oggetto TorreDiControllo, esso potrebbe contenere una "collezione" (quale esattamente, da valutare) di oggetti Pista. Poi sempre TorreDiControllo potrebbe avere un metodo acquisciPista() ed è questo che è synchronized e usa il wait. Restituisce la prima Pista disponibile, altrimenti fa andare in wait il thread fino a quando non se ne trova una libera.
    A quel punto Pista NON deve avere nulla relativo alla sincronizzazione .... un oggetto Pista non lo useranno due thread per volta.
    Poi chiaramente TorreDiControllo dovrà avere un metodo es. rilasciaPista(Pista) che rimette in gioco la pista per altre richieste.

    Anzi, in un design ancora più pulito e semplice, potrebbe essere Pista ad avere un rilascia() ma questo implica che la Pista dovrebbe mantenere una connessione (più o meno "nascosta") con la TorreDiControllo, in modo da rimettere la Pista, sé stessa, in gioco per altre richieste. Si può fare ..... non è impossibile.
  • Re: Di nuovo sui Thread

    andbin ha scritto:


    Qui la questione si può vedere in altro modo: se hai un oggetto TorreDiControllo, esso potrebbe contenere una "collezione" (quale esattamente, da valutare) di oggetti Pista. Poi sempre TorreDiControllo potrebbe avere un metodo acquisciPista() ed è questo che è synchronized e usa il wait. Restituisce la prima Pista disponibile, altrimenti fa andare in wait il thread fino a quando non se ne trova una libera.
    A quel punto Pista NON deve avere nulla relativo alla sincronizzazione .... un oggetto Pista non lo useranno due thread per volta.
    Poi chiaramente TorreDiControllo dovrà avere un metodo es. rilasciaPista(Pista) che rimette in gioco la pista per altre richieste.
    Ciao andbin, non sono riuscito a non usare un metodo sincronizzato nella classe Pista.
    Mi sono perso nel metodo acquisciPista() , non ho usato il wait() e non ho creato il metodo rilasciaPista(Pista) ....sinceramente non ho capito come usarlo.
    Non ho usato neanche il notifyAll() perché non serviva per come l'ho impostato.

    sebbene il programma funzioni, l'assegnazione delle piste ai Thread e come capire se erano in uso non mi fa impazzire, anzi, mi sembra tutto incasinato e poco leggibile....anzi più tendente a programmazione procedurale.

    Come migliorare il codice? anzi, come riscrivere il metodo acquisisciPista in modo da capire quale pista è libera e come rilasciarla?
    
    public class Aereo extends Thread {
    	private String name;
    
    	public Aereo(String nome) {
    		this.name=nome;
    		System.out.println("creato " + this.name);
    	}
    
    	@Override 
    	public void run(){
    		TorreDiControllo.getInstance().controlliPreVolo(this);
    		TorreDiControllo.getInstance().acquisciPista(this);
    	}
    	
    	@Override
    	public String toString() {
    		return this.getName() + " - " + name;
    
    	}
    }
    
    
    public class Pista {
    	private String nome;
    	private int index;
    	private boolean inUso;
    
    	public Pista(String nome, int index, boolean inUso) {
    		this.nome=nome;
    		this.index=index; //posizione della pista nell'array
    		this.inUso=inUso;
    	}
    
    	public int getIndex() {
    		return index;
    	}
    	public boolean getInUso() {
    		return inUso;
    	}
    	public synchronized void permettiDecollo(Aereo aereo) {
    		inUso = true;
    		int tempo = (int)(Math.random()*2)+1;
    		System.out.println(aereo + " sta decollando su " + nome + ". impiega " + tempo + " secondi!");
    		try {
    			Thread.sleep(tempo*1000);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		inUso = false;
    		System.out.println(aereo + " è decollato da " + nome + ". Pista libera!");
    		//notifyAll();
    	}
    }
    
    public class TorreDiControllo {
    	private static TorreDiControllo instance;    
    	private Pista[] piste = new Pista[3];
    
    	public TorreDiControllo() {
    		for(int i=0; i < piste.length; i++) {
    			piste[i]=new Pista("Pista "+i, i, false);
    		}
    	}
    
    	public synchronized static TorreDiControllo getInstance() {        
    		if (instance == null) {            
    			instance = new TorreDiControllo();        
    		}        
    		return instance;    
    	}  
    
    	public synchronized void controlliPreVolo(Aereo aereo) {
    		int tempo = (int)(Math.random()*5) + 1;
    		System.out.println(aereo + " sta FACENDO i controlli in " + tempo + " secondi");
    		try {
    			wait(tempo * 1000);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		System.out.println(aereo + " ha TERMINATO i controlli");
    	}
    
    	public void acquisciPista(Aereo aereo) {
    		boolean cicla=true;
    		while (cicla) {
    			for(Pista p: piste) {
    				if (!p.getInUso()) {
    					p.permettiDecollo(aereo);
    					cicla=false;
    					break;
    				}
    			}
    		}
    	}
    }
    
    public class Tester {
    	public static void main(String[] args) {
    		Aereo[] aereo= new Aereo[10];
    		for (int i=0; i < aereo.length;i++) {
    			aereo[i] = new Aereo("Aereo " + (i + 1));
    		}
    		for (Aereo a:aereo) {
    			a.start();
    		}
    	}
    }
    
    come vedi il metodo acquisisciPista() è veramente incasinato.
    mi sono impicciato nel trovare la "pista libera"

    il risultato del programma però non fa vedere l'uso contemporaneo della risolsa da due thread diversi
    (questo sotto windows)
    
    creato Aereo 1
    creato Aereo 2
    creato Aereo 3
    creato Aereo 4
    creato Aereo 5
    creato Aereo 6
    creato Aereo 7
    creato Aereo 8
    creato Aereo 9
    creato Aereo 10
    Thread-0 - Aereo 1 sta FACENDO i controlli in 2 secondi
    Thread-4 - Aereo 5 sta FACENDO i controlli in 3 secondi
    Thread-1 - Aereo 2 sta FACENDO i controlli in 1 secondi
    Thread-2 - Aereo 3 sta FACENDO i controlli in 4 secondi
    Thread-3 - Aereo 4 sta FACENDO i controlli in 5 secondi
    Thread-9 - Aereo 10 sta FACENDO i controlli in 1 secondi
    Thread-8 - Aereo 9 sta FACENDO i controlli in 3 secondi
    Thread-7 - Aereo 8 sta FACENDO i controlli in 2 secondi
    Thread-6 - Aereo 7 sta FACENDO i controlli in 4 secondi
    Thread-5 - Aereo 6 sta FACENDO i controlli in 1 secondi
    Thread-1 - Aereo 2 ha TERMINATO i controlli
    Thread-1 - Aereo 2 sta decollando su Pista 0. impiega 2 secondi!
    Thread-9 - Aereo 10 ha TERMINATO i controlli
    Thread-9 - Aereo 10 sta decollando su Pista 1. impiega 1 secondi!
    Thread-5 - Aereo 6 ha TERMINATO i controlli
    Thread-5 - Aereo 6 sta decollando su Pista 2. impiega 2 secondi!
    Thread-9 - Aereo 10 è decollato da Pista 1. Pista libera!
    Thread-7 - Aereo 8 ha TERMINATO i controlli
    Thread-7 - Aereo 8 sta decollando su Pista 1. impiega 2 secondi!
    Thread-0 - Aereo 1 ha TERMINATO i controlli
    Thread-5 - Aereo 6 è decollato da Pista 2. Pista libera!
    Thread-1 - Aereo 2 è decollato da Pista 0. Pista libera!
    Thread-0 - Aereo 1 sta decollando su Pista 2. impiega 2 secondi!
    Thread-4 - Aereo 5 ha TERMINATO i controlli
    Thread-8 - Aereo 9 ha TERMINATO i controlli
    Thread-4 - Aereo 5 sta decollando su Pista 0. impiega 2 secondi!
    Thread-2 - Aereo 3 ha TERMINATO i controlli
    Thread-7 - Aereo 8 è decollato da Pista 1. Pista libera!
    Thread-2 - Aereo 3 sta decollando su Pista 1. impiega 1 secondi!
    Thread-6 - Aereo 7 ha TERMINATO i controlli
    Thread-2 - Aereo 3 è decollato da Pista 1. Pista libera!
    Thread-3 - Aereo 4 ha TERMINATO i controlli
    Thread-8 - Aereo 9 sta decollando su Pista 1. impiega 2 secondi!
    Thread-0 - Aereo 1 è decollato da Pista 2. Pista libera!
    Thread-4 - Aereo 5 è decollato da Pista 0. Pista libera!
    Thread-3 - Aereo 4 sta decollando su Pista 2. impiega 1 secondi!
    Thread-3 - Aereo 4 è decollato da Pista 2. Pista libera!
    Thread-8 - Aereo 9 è decollato da Pista 1. Pista libera!
    Thread-6 - Aereo 7 sta decollando su Pista 1. impiega 2 secondi!
    Thread-6 - Aereo 7 è decollato da Pista 1. Pista libera!
    
  • Re: Di nuovo sui Thread

    tagan ha scritto:


    Ciao andbin, non sono riuscito a non usare un metodo sincronizzato nella classe Pista.
    Mi sono perso nel metodo acquisciPista() , non ho usato il wait() e non ho creato il metodo rilasciaPista(Pista) ....sinceramente non ho capito come usarlo.
    Non ho usato neanche il notifyAll() perché non serviva per come l'ho impostato.
    Beh, la logica sarebbe abbastanza semplice: se in TorreDiControllo tieni una "collezione" di oggetti Pista (potrebbe essere es. un ArrayList o LinkedList), quando fornisci a qualcuno una Pista, la rimuovi fisicamente dalla collezione (e poi un "rilascia" la rimette nella collezione).
    E quindi un acquisisciPista() si dovrebbe bloccare nel wait() quando la collezione è ...... ?
  • Re: Di nuovo sui Thread

    andbin ha scritto:


    tagan ha scritto:


    Ciao andbin, non sono riuscito a non usare un metodo sincronizzato nella classe Pista.
    Mi sono perso nel metodo acquisciPista() , non ho usato il wait() e non ho creato il metodo rilasciaPista(Pista) ....sinceramente non ho capito come usarlo.
    Non ho usato neanche il notifyAll() perché non serviva per come l'ho impostato.
    Beh, la logica sarebbe abbastanza semplice: se in TorreDiControllo tieni una "collezione" di oggetti Pista (potrebbe essere es. un ArrayList o LinkedList), quando fornisci a qualcuno una Pista, la rimuovi fisicamente dalla collezione (e poi un "rilascia" la rimette nella collezione).
    E quindi un acquisisciPista() si dovrebbe bloccare nel wait() quando la collezione è ...... ?
    vuota. hai ragione.
    provo quest'altro modo. Grazie.
    Tagan
    PS ma a questo punto allora, visto che fa tutto la classe TorreDiControllo, posso eliminare anche la classe Pista e fare un ArrayList di Stringhe con solo il nome della Pista, poi per il "decollo" e rilascio pista, potrei usare un nuovo metodo.

    Anzi, meglio. se faccio una shallow copy della pista prima di eliminarla dall'arraylist , metto il metodo rilasciaPista nella classe pista col notifyAll e poi riaggiungo lo stesso oggetto all'arraylist?
  • Re: Di nuovo sui Thread

    andbin ha scritto:


    E quindi un acquisisciPista() si dovrebbe bloccare nel wait() quando la collezione è ...... ?
    Mi va in errore
    
    java.lang.IllegalMonitorStateException
    	at java.lang.Object.wait(Native Method)
    	at java.lang.Object.wait(Unknown Source)
    	at TorreDiControllo.acquisciPista(TorreDiControllo.java:37)
    	at Aereo.run(Aereo.java:14)
    
    nel codice aereo.wait()
    
    public synchronized void acquisciPista(Aereo aereo) {
    		if (piste.size()==0)
    			try {
    				aereo.wait();                                   <<--- QUESTO E'   :  at TorreDiControllo.acquisciPista(TorreDiControllo.java:37)
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		else {
    			pistaUso = piste.get(piste.size()-1);
    			piste.remove(piste.size()-1);
    			permettiDecollo(aereo,pistaUso);
    		}
    	}
    
    il metodo run di Aereo è questo
    
    @Override 
    	public void run(){
    		TorreDiControllo.getInstance().controlliPreVolo(this);
    		TorreDiControllo.getInstance().acquisciPista(this);            <<--- QUESTO E'   :   at Aereo.run(Aereo.java:14)
    
    	}
    
  • Re: Di nuovo sui Thread

    tagan ha scritto:


    Mi va in errore
    
    java.lang.IllegalMonitorStateException
    
    Sì, perché i wait/notify/notifyAll si devono invocare su di un oggetto di cui il thread corrente ha acquisito il lock.

    Il synchronized è su un metodo (di istanza) di TorreDiControllo, quindi l'oggetto di lock è la istanza di TorreDiControllo. Ma il wait l'hai fatto sul aereo (che comunque non ha senso).

    Inoltre il wait() va sempre messo dentro un while ... non un if.
    Insomma, non "se" ma "finché la condizione X regge" allora STAI in wait.
    Ci sono motivazioni storiche/pratiche per questo.

    E generalmente il InterruptedException non lo si cattura lì ma lo si fa uscire fuori dal metodo "bloccante".

    Inoltre nota che il remove(index) restituisce già l'oggetto che ha rimosso (in sostanza: il get non servirebbe!)
  • Re: Di nuovo sui Thread

    andbin ha scritto:


    tagan ha scritto:


    Mi va in errore
    
    java.lang.IllegalMonitorStateException
    
    Sì, perché i wait/notify/notifyAll si devono invocare su di un oggetto di cui il thread corrente ha acquisito il lock.
    Capito.
    funziona tutto facendo questa modifica. i metodi che hanno wait() e notifyAll() vengono chiamati da Thread.
    in questo modo no ho più l'errore IllegalMonitorStateException

    in pratica ho il metodo run in questo modo
    
    	@Override 
    	public void run(){
    		TorreDiControllo.getInstance().controlliPreVolo(this);   <<<----- wait(X)  ...per fermare il thread per X secondi ma non bloccare la risorsa
    		Pista p = TorreDiControllo.getInstance().acquisciPista(this);   <<<----- wait()  fino al notify, se non ci sono piste disponibili e remove()
    		TorreDiControllo.getInstance().decolla(this);   <<<----- sleep(Y)  ...per bloccare la risorsa per Y secondi
    		TorreDiControllo.getInstance().rilasciaPista(p);    <<<----- notifyAll() per liberare i thread e rimettere la pista nell'ArrayList
    	}
    
    dove è il problema? .......se è un problema:
    come puoi vedere, il Thread 3 - Aereo 4 impiega 10 secondi a decollare, in questo tempo, tutti gli altri thread avrebbero dovuto terminare i controlli e stampare "TERMINATI i controlli", invece lo fanno dopo il "decollo" di Aereo 4, come se questo Thread, bloccasse tutto anche le altre risorse.
    Ti posto il risultato
    
    Thread-0 - Aereo 1 sta FACENDO i controlli in 8 secondi
    Thread-3 - Aereo 4 sta FACENDO i controlli in 2 secondi
    Thread-1 - Aereo 2 sta FACENDO i controlli in 5 secondi
    Thread-4 - Aereo 5 sta FACENDO i controlli in 8 secondi
    Thread-5 - Aereo 6 sta FACENDO i controlli in 6 secondi
    Thread-6 - Aereo 7 sta FACENDO i controlli in 6 secondi
    Thread-7 - Aereo 8 sta FACENDO i controlli in 3 secondi
    Thread-9 - Aereo 10 sta FACENDO i controlli in 3 secondi
    Thread-8 - Aereo 9 sta FACENDO i controlli in 2 secondi
    Thread-2 - Aereo 3 sta FACENDO i controlli in 6 secondi
    Thread-3 - Aereo 4 ha TERMINATO i controlli
    Thread-3 - Aereo 4 sta decollando su Pista 2. impiega 10 secondi!
    Thread-3 - Aereo 4 è decollato da Pista 2. Pista libera!
    Thread-4 - Aereo 5 ha TERMINATO i controlli
    Thread-4 - Aereo 5 sta decollando su Pista 1. impiega 1 secondi!
    Thread-4 - Aereo 5 è decollato da Pista 1. Pista libera!
    Thread-0 - Aereo 1 ha TERMINATO i controlli
    Thread-0 - Aereo 1 sta decollando su Pista 0. impiega 10 secondi!
    Thread-0 - Aereo 1 è decollato da Pista 0. Pista libera!
    Thread-5 - Aereo 6 ha TERMINATO i controlli
    Thread-5 - Aereo 6 sta decollando su Pista 0. impiega 1 secondi!
    Thread-5 - Aereo 6 è decollato da Pista 0. Pista libera!
    Thread-6 - Aereo 7 ha TERMINATO i controlli
    Thread-6 - Aereo 7 sta decollando su Pista 0. impiega 8 secondi!
    Thread-6 - Aereo 7 è decollato da Pista 0. Pista libera!
    Thread-2 - Aereo 3 ha TERMINATO i controlli
    Thread-2 - Aereo 3 sta decollando su Pista 0. impiega 3 secondi!
    Thread-2 - Aereo 3 è decollato da Pista 0. Pista libera!
    Thread-1 - Aereo 2 ha TERMINATO i controlli
    Thread-9 - Aereo 10 ha TERMINATO i controlli
    Thread-7 - Aereo 8 ha TERMINATO i controlli
    Thread-8 - Aereo 9 ha TERMINATO i controlli
    Thread-8 - Aereo 9 sta decollando su Pista 2. impiega 4 secondi!
    Thread-8 - Aereo 9 è decollato da Pista 2. Pista libera!
    Thread-7 - Aereo 8 sta decollando su Pista 1. impiega 9 secondi!
    Thread-7 - Aereo 8 è decollato da Pista 1. Pista libera!
    Thread-9 - Aereo 10 sta decollando su Pista 1. impiega 8 secondi!
    Thread-9 - Aereo 10 è decollato da Pista 1. Pista libera!
    Thread-1 - Aereo 2 sta decollando su Pista 0. impiega 8 secondi!
    Thread-1 - Aereo 2 è decollato da Pista 0. Pista libera!
    
    Come si vede nei "CONTROLLI", Aereo 4 e Aereo 9 avrebbero dovuto terminare i controlli dopo soli 2 secondi, invece il 4 ha terminato in 2 secondi, mentre il 9 dopo circa 20 secondi.

    Questo è dovuto al fatto che il wait o lo sleep mettono a dormire tutto e il notifyAll risveglia i Thread che cercano di rimpossessarsi delle risorse, ma il primo che arriva riblocca tutto? .....il 9 è solo stato sfortunato insomma!
    ho provato a usare i secondi (da 1 a 10) nel setPriority(), ma sembra non sunzionare!

    Cmq, diciamo che la concorrenza l'ho gestita questo è l'importante, il resto è solo essere pignoli...!

    Come sempre grazie dei consigli e correzioni.
    Tagan
  • Re: Di nuovo sui Thread

    ANZI NO..... ripensandoci non funziona bene..... avrebbe dovuto scrivere un caso del tipo
    
    Thread-5 - Aereo 6 ha TERMINATO i controlli
    Thread-6 - Aereo 7 ha TERMINATO i controlli
    Thread-5 - Aereo 6 sta decollando su Pista 0. impiega 1 secondi!
    Thread-6 - Aereo 7 sta decollando su Pista 1. impiega 8 secondi!
    Thread-2 - Aereo 3 ha TERMINATO i controlli
    Thread-5 - Aereo 6 è decollato da Pista 0. Pista libera!
    Thread-2 - Aereo 3 sta decollando su Pista 2. impiega 3 secondi!
    Thread-2 - Aereo 3 è decollato da Pista 2. Pista libera!
    Thread-6 - Aereo 7 è decollato da Pista 1. Pista libera!
    
    Cioè, avrebbe dovuto usare tre piste contemporaneamente, invece ne usa sempre una per volta anche se sono oggetti diversi.
    L'errore sarebbe questo
    
    Thread-5 - Aereo 6 sta decollando su Pista 0. impiega 1 secondi!
    Thread-6 - Aereo 7 sta decollando su Pista 0. impiega 8 secondi!
    
    Entrambi su Pista 0 contemporaneamente, questo non succede, ma il Multi-Threading non si vede.....ho sbagliato qualcosa giusto?
  • Re: Di nuovo sui Thread

    tagan ha scritto:


    
    		TorreDiControllo.getInstance().controlliPreVolo(this);   <<<----- wait(X)  ...per fermare il thread per X secondi ma non bloccare la risorsa
    		Pista p = TorreDiControllo.getInstance().acquisciPista(this);   <<<----- wait()  fino al notify, se non ci sono piste disponibili e remove()
    		TorreDiControllo.getInstance().decolla(this);   <<<----- sleep(Y)  ...per bloccare la risorsa per Y secondi
    		TorreDiControllo.getInstance().rilasciaPista(p);    <<<----- notifyAll() per liberare i thread e rimettere la pista nell'ArrayList
    
    Scusa ma perché decolla è in TorreDiControllo? (e non usi la Pista?)
  • Re: Di nuovo sui Thread

    andbin ha scritto:


    tagan ha scritto:


    
    		TorreDiControllo.getInstance().controlliPreVolo(this);   <<<----- wait(X)  ...per fermare il thread per X secondi ma non bloccare la risorsa
    		Pista p = TorreDiControllo.getInstance().acquisciPista(this);   <<<----- wait()  fino al notify, se non ci sono piste disponibili e remove()
    		TorreDiControllo.getInstance().decolla(this);   <<<----- sleep(Y)  ...per bloccare la risorsa per Y secondi
    		TorreDiControllo.getInstance().rilasciaPista(p);    <<<----- notifyAll() per liberare i thread e rimettere la pista nell'ArrayList
    
    Scusa ma perché decolla è in TorreDiControllo? (e non usi la Pista?)
    Prima stava su pista, in fatti faceva p.permettiDecollo(this) eppure non funziona.
    decolla in torre di controlli è
    TorreDiControllo.getInstance().decolla(this,p);
    e poi
    
    	public synchronized void decolla(Aereo aereo, Pista p) {
    		p.permettiDecollo(aereo);
    	}
    
    mentre su Pista:
    
    	public synchronized void permettiDecollo(Aereo aereo) {
    		int tempo = (int)(Math.random()*10)+1;
    		System.out.println(aereo + " sta decollando su " + nome + ". impiega " + tempo + " secondi!");
    		try {
    			//Thread.sleep(tempo*1000);
    			wait(tempo*1000);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		System.out.println(aereo + " è decollato da " + nome + ". Pista libera!");
    	}
    
    sto tentando di capire perché se nel RUN metto il metodo di Pista e commneto il decolla(), mi restituisce:
    
    creato Aereo 1
    creato Aereo 2
    creato Aereo 3
    creato Aereo 4
    creato Aereo 5
    creato Aereo 6
    creato Aereo 7
    creato Aereo 8
    creato Aereo 9
    creato Aereo 10
    Thread-1 - Aereo 2 sta FACENDO i controlli in 7 secondi
    Thread-0 - Aereo 1 sta FACENDO i controlli in 4 secondi
    Thread-2 - Aereo 3 sta FACENDO i controlli in 10 secondi
    Thread-3 - Aereo 4 sta FACENDO i controlli in 5 secondi
    Thread-4 - Aereo 5 sta FACENDO i controlli in 9 secondi
    Thread-5 - Aereo 6 sta FACENDO i controlli in 10 secondi
    Thread-6 - Aereo 7 sta FACENDO i controlli in 4 secondi
    Thread-7 - Aereo 8 sta FACENDO i controlli in 1 secondi
    Thread-9 - Aereo 10 sta FACENDO i controlli in 3 secondi
    Thread-8 - Aereo 9 sta FACENDO i controlli in 1 secondi
    Thread-7 - Aereo 8 ha TERMINATO i controlli
    Thread-7 - Aereo 8 sta decollando su Pista 2. impiega 4 secondi!
    Thread-8 - Aereo 9 ha TERMINATO i controlli
    Thread-8 - Aereo 9 sta decollando su Pista 1. impiega 9 secondi!
    Thread-9 - Aereo 10 ha TERMINATO i controlli
    Thread-9 - Aereo 10 sta decollando su Pista 0. impiega 8 secondi!
    Thread-0 - Aereo 1 ha TERMINATO i controlli
    Thread-6 - Aereo 7 ha TERMINATO i controlli
    Thread-3 - Aereo 4 ha TERMINATO i controlli
    Thread-7 - Aereo 8 è decollato da Pista 2. Pista libera!
    Thread-3 - Aereo 4 sta decollando su Pista 2. impiega 8 secondi!
    Thread-5 - Aereo 6 ha TERMINATO i controlli
    Exception in thread "Thread-0" Thread-4 - Aereo 5 ha TERMINATO i controlli
    Thread-2 - Aereo 3 ha TERMINATO i controlli
    Thread-1 - Aereo 2 ha TERMINATO i controlli
    Exception in thread "Thread-6" java.lang.ArrayIndexOutOfBoundsException: -1
    	at java.util.ArrayList.elementData(ArrayList.java:418)
    	at java.util.ArrayList.remove(ArrayList.java:495)
    	at TorreDiControllo.acquisciPista(Tester.java:82)
    	at Aereo.run(Tester.java:14)
    java.lang.ArrayIndexOutOfBoundsException: -1
    	at java.util.ArrayList.elementData(ArrayList.java:418)
    	at java.util.ArrayList.remove(ArrayList.java:495)
    	at TorreDiControllo.acquisciPista(Tester.java:82)
    	at Aereo.run(Tester.java:14)
    Thread-8 - Aereo 9 è decollato da Pista 1. Pista libera!
    Exception in thread "Thread-2" Thread-1 - Aereo 2 sta decollando su Pista 1. impiega 8 secondi!
    Exception in thread "Thread-4" java.lang.ArrayIndexOutOfBoundsException: -1
    	at java.util.ArrayList.elementData(ArrayList.java:418)
    	at java.util.ArrayList.remove(ArrayList.java:495)
    	at TorreDiControllo.acquisciPista(Tester.java:82)
    	at Aereo.run(Tester.java:14)
    Exception in thread "Thread-5" java.lang.ArrayIndexOutOfBoundsException: -1
    	at java.util.ArrayList.elementData(ArrayList.java:418)
    	at java.util.ArrayList.remove(ArrayList.java:495)
    	at TorreDiControllo.acquisciPista(Tester.java:82)
    	at Aereo.run(Tester.java:14)
    java.lang.ArrayIndexOutOfBoundsException: -1
    	at java.util.ArrayList.elementData(ArrayList.java:418)
    	at java.util.ArrayList.remove(ArrayList.java:495)
    	at TorreDiControllo.acquisciPista(Tester.java:82)
    	at Aereo.run(Tester.java:14)
    Thread-9 - Aereo 10 è decollato da Pista 0. Pista libera!
    Thread-3 - Aereo 4 è decollato da Pista 2. Pista libera!
    Thread-1 - Aereo 2 è decollato da Pista 1. Pista libera!
    
    molto probabilmente perché l'ADD della pista liberata, lo faccio in rilasciaPista di TorreDiControllo......
    dovrei rifarlo da zero il programma. Si è tutto incasinato!
    Quando ho un bel po di tempo, lo ridisegno tutto e poi lo riscrivo. Cosi non ci sto capendo più niente!
  • Re: Di nuovo sui Thread

    tagan ha scritto:


    
    		try {
    			//Thread.sleep(tempo*1000);
    			wait(tempo*1000);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    
    Il wait NON si usa così.
  • Re: Di nuovo sui Thread

    andbin ha scritto:


    tagan ha scritto:


    
    		try {
    			//Thread.sleep(tempo*1000);
    			wait(tempo*1000);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    
    Il wait NON si usa così.
    Perché non si usa così? E' scritto sia nella guida ufficiale che nel testo che sto leggendo di Claudio De Sio Cesari, "Manuale di Java 8" e ci sono molti esempi con wait(millisecondi)
  • Re: Di nuovo sui Thread

    tagan ha scritto:


    Perché non si usa così? E' scritto sia nella guida ufficiale che nel testo che sto leggendo di Claudio De Sio Cesari, "Manuale di Java 8" e ci sono molti esempi con wait(millisecondi)
    No, non è questione dei millisecondi. Il wait va usato in un ciclo (normalmente un while) che deve testare la condizione che deve "reggere" per far stare in wait il thread.
    E comunque non si usa solo per far passare del tempo (per quello c'è sleep).
  • Re: Di nuovo sui Thread

    andbin ha scritto:


    tagan ha scritto:


    Perché non si usa così? E' scritto sia nella guida ufficiale che nel testo che sto leggendo di Claudio De Sio Cesari, "Manuale di Java 8" e ci sono molti esempi con wait(millisecondi)
    No, non è questione dei millisecondi. Il wait va usato in un ciclo (normalmente un while) che deve testare la condizione che deve "reggere" per far stare in wait il thread.
    E comunque non si usa solo per far passare del tempo (per quello c'è sleep).
    Ah ok. infatti è anche per quello che lo voglio riscrivere tutto. ho visto altri esempi in cui si trova in un ciclo while e usano una variabile booleana che viene settata al termine di una certa operazione. una cosa del genere:
    
    public syncronized int get() {
    	while (disponibile == false) {
    		try { wait(); } catch(InterruptedException e){}
     	}
    	disponibile = false;
    	notifyAll();
     	return valore;
    } 
    
    voglio usare questo esempio, modificandolo per le mie esigenze, magari capisco una volta per tutte i metodi wait, notify ....e quello più strano join...!
    Grazie.
Devi accedere o registrarti per scrivere nel forum
16 risposte