Newsgroup: it.comp.java
Titolo: Sleep in Java?

Scusatemi avrei bisogno di una semplice funzione che mi permetta di 
fermare l'esecuzione per un periodo di tempo. In C utilizzo la sleep, in 
java? Ho trovato Thread.sleep(period) ma non sempre funzionare gran chè 
bene...qualche alternativa?
Grazie mille!



scusa perchè non dovrebbe funzionare bene? è l'unica standard
che problema ti da?
(ps... ricordati sempre di catturare InterruptedException)
-- 
Fermiamo scientology prima che sia troppo tardi!!!
http://xenu.com-it.net
 - 
http://xenu.freewinds.cx/
 - 
http://www.xenu.net/
(per rispondere personalmente leva IlDitoDalCulo)

 (ps... ricordati sempre di catturare InterruptedException)
Ma forse funziona anche, solo che lo sto utilizzando all'interno di un 
programma grafico (fatto le le swing) e sono abbastanza niubbo di java e 
sembra che al posto di stampare i valori ogni qual volta scade lo sleep, 
li stampa tutti insieme alla fine, dopo che ha aspettato il tempo.
Forse devo in qualche modo utilizzare sleep accoppiato a qualche 
funzione di paint?



MAI - MAI - MAI e ripeto
*MAI*
fermare e/o rallentare il thread di gestione degli eventi Swing/AWT!!!!!!!
Ottieni esattamente l'effetto che hai descritto.
Quello che devi fare è
1) raggruppare tutta la sequenza che comprende gli "sleep" in un solo
metodo, che chiamerai ad esempio eseguiLavoroLungo()
2) creare un thread che andrà a richiamare questo metodo
3) dal tuo metodo, quando devi aggiornare la gui, fallo usando
javax.swing.SwingUtilites.invokeLater() - leggi la documentazione per
maggiori info
4) Studia meglio come funziona Swing, prima di fare cose che siano più
complesse di un get/set di proprietà *immediata* in risposta agli eventi
se serve una mano in più, posta direttamente il codice incriminato e vediamo
di correggerlo.


 
Allora innanzitutto grazie mille per la disponibilità.
Il codice (non tutto perchè è abbastanza lungo) è il seguente:
public void actionPerformed(ActionEvent e) {
if(e.getSource() == Start) {
			if(bstart == true) bstart = false;
			else bstart = true;
			if(bstart == true){
				while(bstart == true){
					repaint();
 
					numera();
					repaint();
 
					iter++;
					if(iter > 100){
						iter = 0;
						break;
					}
				}
			}
		}
		if(e.getSource() == Stop){
			bstart = false;
		}
	}
 
 
	private void numera(){
		try{
			Thread.sleep(100);
 
			lchan.setText(Integer.toString(midi.myn[track].myp[iter].chan));
			lpitch.setText(Integer.toString(midi.myn[track].myp[iter].nota));
			lvel.setText(Integer.toString(midi.myn[track].myp[iter].velocity));
		}
		catch(InterruptedException e){
			System.out.println("Sleep Interrupted");
		}
	}
Praticamente ci sono 2 bottoni e 3 label. I bottoni sono Start e Stop. 
Quando premo su Start dovrebbe iniziare a cambiare la il text delle 
label seguendo un ritmo (che è scandito da sleep(100)). Quando premo su 
Stop poi il tutto dobrebbe fermarsi.
Intanto vedo di recuperare informazioni sui punti 1, 2, 3 e 4 :)

 Intanto vedo di recuperare informazioni sui punti 1, 2, 3 e 4 :)
Vai tranquillo, dovrebbe bastare. Ti faccio uno "schema modello" a cui
dovrai adattare il resto, cosě non dovresti piů avere blocchi.


 dovrai adattare il resto, cosě non dovresti piů avere blocchi.
...
public void actionPerformed(ActionEvent e) {
  if (e.getSource()==Start) {
    if (!bstart) bstart=false; else bstart=true;
    if (bstart) {
      Thread numeraThread=new Thread(new Runnable () {
        public void run() {numeraCiclo();}
      });
    }
  }
  if (e.getSource()==Stop) {
    bstart=false;
  }
}
private void numeraCiclo() {
  while (bstart) {
    //Questo "sleep" non blocca il thread di gestione degli
    //eventi
    try {Thread.sleep(100);} catch (InterruptedException ex) {}
 
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        //Qui puoi interagire con il thread di gestione degli
        //eventi, invokeLater č stato creato apposta per questo
 
        lchan.setText(Integer.toString(midi.myn[track].myp[iter].chan));
	lpitch.setText(Integer.toString(midi.myn[track].myp[iter].nota));
	lvel.setText(Integer.toString(midi.myn[track].myp[iter].velocity));  
      }
    });    
    iter++;
    if (iter>100) {iter=0;break;}
  }
}
...
Ho approfittato del fatto che usi una variabile booleana a livello di classe
(bstart) per indicare se il ciclo deve girare o meno. Complimenti (sinceri),
hai pensato all'elaborazione parallela prima ancora di pensare ai Thread!!!
Questo infatti č il metodo piů comune (diciamo anche l'unico) per
interrompere l'elaborazione di un Thread senza usare Thread.stop() (che č
deprecato).
Una piccola nota: visto l'uso che fai di bstart, ti conviene dichiararla
come
private volatile boolean bstart;
Questo impedisce al compilatore di ottimizzarla, evitando il rischio di
ottenere valori sfalsati (se ottimizzata, potrebbe capitare che un suo
assegnamento non venga eseguito)
In bocca al lupo!!!


 dovrai adattare il resto, cosě non dovresti piů avere blocchi.
...
public void actionPerformed(ActionEvent e) {
  if (e.getSource()==Start) {
    if (!bstart) bstart=false; else bstart=true;
    if (bstart) {
      Thread numeraThread=new Thread(new Runnable () {
        public void run() {numeraCiclo();}
      });
      numeraThread.start();
    }
  }
  if (e.getSource()==Stop) {
    bstart=false;
  }
}
private void numeraCiclo() {
  while (bstart) {
    //Questo "sleep" non blocca il thread di gestione degli
    //eventi
    try {Thread.sleep(100);} catch (InterruptedException ex) {}
 
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        //Qui puoi interagire con il thread di gestione degli
        //eventi, invokeLater č stato creato apposta per questo
 
        lchan.setText(Integer.toString(midi.myn[track].myp[iter].chan));
	lpitch.setText(Integer.toString(midi.myn[track].myp[iter].nota));
	lvel.setText(Integer.toString(midi.myn[track].myp[iter].velocity));  
      }
    });    
    iter++;
    if (iter>100) {iter=0;break;}
  }
}
...
Ho approfittato del fatto che usi una variabile booleana a livello di classe
(bstart) per indicare se il ciclo deve girare o meno. Complimenti (sinceri),
hai pensato all'elaborazione parallela prima ancora di pensare ai Thread!!!
Questo infatti č il metodo piů comune (diciamo anche l'unico) per
interrompere l'elaborazione di un Thread senza usare Thread.stop() (che č
deprecato).
Una piccola nota: visto l'uso che fai di bstart, ti conviene dichiararla
come
private volatile boolean bstart;
Questo impedisce al compilatore di ottimizzarla, evitando il rischio di
ottenere valori sfalsati (se ottimizzata, potrebbe capitare che un suo
assegnamento non venga eseguito)
In bocca al lupo!!!
-- 


 In bocca al lupo!!!
Crepi!

 Cioč non ho nessuna esperienza di Thread, mi trovo un attimo spiazzato.
Vedila cosě, se puň essere piů semplice:
Nel momento in cui una delle tue procedure *viene chiamata* (call-back) da
Swing, č il sistema grafico che ti sta dicendo ad esempio "l'utente ha
cliccato su questo pulsante, che faccio?" (il famoso actionPerformed() ). In
quel preciso momento ti trovi nel "contesto" del sistema grafico... la tua
procedura viene letteralmente incorporata nel "protocollo" a cui Swing si
attiene per fare quello che deve (disegnare il contenuto della finestra E
fare attenzione alle azioni dell'utente).
E, in attesa che tu finisca, rimane in sospeso.
Proprio per questo tutti i manuali (anche il tutorial sul sito della Sun)
consigliano di concludere la risposta agli eventi nel modo piů *RAPIDO*
possibile. Se nel tuo actionPerformed (o in una qualsiasi procedura che
richiami da li dentro) c'č uno sleep() o in generale se l'elaborazione si
protrae per piů di qualche millisecondo, ecco che l'interfaccia grafica
sembra "piantarsi"... č solo Swing che sta aspettando che tu gli restituisca
il controllo.
Un Thread non č altro che un "processore simulato" (per dirla alla buona)
per permetterti di far eseguire piů parti del tuo programma
*contemporaneamene*. Se guardi bene l'esempio inserito nel tuo codice:
Thread numeraThread=new Thread(new Runnable () {
  public void run() {numeraCiclo();}
});
numeraThread.start();
Prima viene creato il thread (assegnato a numeraThread). Quel costruttore un
po' particolare permette di dire sinteticamente al Thread: "quando parti,
vai ad eseguire la procedura numeraCiclo()". Subito dopo viene richiamato
start(). Questa chiama termina immediatamente, permettendoti di lasciare il
controllo a Swing. Dietro le quinte perň la Java Virtual Machine crea un
percorso separato per l'esecuzione parallela du numeraCiclo(), che viene
lanciato *mentre* Swing continua ad interagire allegramente con l'utente.
A questo punto perň il thread appena creato non puň toccare nulla
dell'ambiente grafico: se il tuo thread cerca di modificare una label nello
stesso momento in cui Swing tenta di ridisegnarla, possono capitare errori
difficilissimi da scovare e risolvere (le cosiddere race conditions). Per
ovviare a questo inconveniente arriva in aiuto invokeLater():
  SwingUtilities.invokeLater(new Runnable() {
    public void run() {
      //Qui puoi interagire con il thread di gestione degli
      //eventi, invokeLater č stato creato apposta per questo
 
      lchan.setText(Integer.toString(midi.myn[track].myp[iter].chan));
      lpitch.setText(Integer.toString(midi.myn[track].myp[iter].nota));
      lvel.setText(Integer.toString(midi.myn[track].myp[iter].velocity));  
    }
  });    
In questo modo stai dicendo a Swing: "appena puoi esegui queste modifiche
sull'interfaccia grafica". Swing prende nota, e appena prima di eseguire il
prossimo ridisegno, esegui il tuo codice modificando il contenuto delle
label senza problemi.
Capito tutto?


 Cioč non ho nessuna esperienza di Thread, mi trovo un attimo spiazzato.
Vedila cosě, se puň essere piů semplice:
Nel momento in cui una delle tue procedure *viene chiamata* (call-back) da
Swing, č il sistema grafico che ti sta dicendo ad esempio "l'utente ha
cliccato su questo pulsante, che faccio?" (il famoso actionPerformed() ). In
quel preciso momento ti trovi nel "contesto" del sistema grafico... la tua
procedura viene letteralmente incorporata nel "protocollo" a cui Swing si
attiene per fare quello che deve (disegnare il contenuto della finestra E
fare attenzione alle azioni dell'utente).
E, in attesa che tu finisca, rimane in sospeso.
Proprio per questo tutti i manuali (anche il tutorial sul sito della Sun)
consigliano di concludere la risposta agli eventi nel modo piů *RAPIDO*
possibile. Se nel tuo actionPerformed (o in una qualsiasi procedura che
richiami da li dentro) c'č uno sleep() o in generale se l'elaborazione si
protrae per piů di qualche millisecondo, ecco che l'interfaccia grafica
sembra "piantarsi"... č solo Swing che sta aspettando che tu gli restituisca
il controllo.
Un Thread non č altro che un "processore simulato" (per dirla alla buona)
per permetterti di far eseguire piů parti del tuo programma
*contemporaneamene*. Se guardi bene l'esempio inserito nel tuo codice:
Thread numeraThread=new Thread(new Runnable () {
  public void run() {numeraCiclo();}
});
numeraThread.start();
Prima viene creato il thread (assegnato a numeraThread). Quel costruttore un
po' particolare permette di dire sinteticamente al Thread: "quando parti,
vai ad eseguire la procedura numeraCiclo()". Subito dopo viene richiamato
start(). Questa chiamata termina immediatamente, permettendoti di lasciare
il controllo a Swing. Dietro le quinte perň la Java Virtual Machine crea un
percorso separato per l'esecuzione parallela di numeraCiclo(), che viene
lanciato *mentre* Swing continua ad interagire allegramente con l'utente.
A questo punto perň il thread appena creato non puň toccare nulla
dell'ambiente grafico: se il tuo thread cerca di modificare una label nello
stesso momento in cui Swing tenta di ridisegnarla, possono capitare errori
difficilissimi da scovare e risolvere (le cosiddere race conditions). Per
ovviare a questo inconveniente arriva in aiuto invokeLater():
  SwingUtilities.invokeLater(new Runnable() {
    public void run() {
      //Qui puoi interagire con il thread di gestione degli
      //eventi, invokeLater č stato creato apposta per questo
 
      lchan.setText(Integer.toString(midi.myn[track].myp[iter].chan));
      lpitch.setText(Integer.toString(midi.myn[track].myp[iter].nota));
      lvel.setText(Integer.toString(midi.myn[track].myp[iter].velocity));  
    }
  });    
In questo modo stai dicendo a Swing: "appena puoi esegui queste modifiche
sull'interfaccia grafica". Swing prende nota, e appena prima di eseguire il
prossimo ridisegno, esegue il tuo codice modificando il contenuto delle
label senza problemi.
Capito tutto?
-- 


 Capito tutto?
Si abbastanza!
Che dire sono senza parole! La tua gentilezza e disponibilità è unica. 
Ti ringrazio ancora moltissimo!