Newsgroup: it.comp.java
Titolo: Thread e JTextArea

Qualcuno puo darmi un aiuto con questi due problemini...
Come faccio a fare in modo che quando inserisco del testo in un JTextArea
(utilizzo il metodo append)  inserito a sua volta in un JScrollPane la finestra
scorra automaticamente in modo da farmi vedere le ultime righe inserite?
All'interno del metodo run di una classe che implementa Runnable ho inserito
il seguente codice:
running=true;
while (running)
{
   if (!vector.empty())
   {
	// fa qualcosa con l'oggetto vector tra cui
	// vector.remove(0);
   }
}	
E normale che il metodo utilizzi il 95% della cpu o dipende dal fatto che vector
(è un oggetto Vector) è solitamente vuoto? Se lo è come posso rosolvere il
problema (ho provato a diminuire la priorità ma non cambia niente)
Grazie per eventuali risposte
Angelo


Stai facendo quello che comunemente si chiama "busy waiting", cioe'
continui a testare o a fare il polling indefinitivamente per il
verificarsi di una certa situazione. 
Una soluzione migliore e' prendere l'approccio inverso. Il tuo vettore,
quando "riempito", emette un segnale verso il thread che e' incaricato di
reagire (nel tuo caso, semplicemente svuotandolo). 
-- 
God is Real, unless declared Integer.
ObjectZone - 
http://space.tin.it/computer/csadun

 reagire (nel tuo caso, semplicemente svuotandolo).
Grazie per la risposta. In realtà quello che mi hai consiglliato è proprio
quello che cercavo di fare (ho preso spunto proprio dall'articolo presente
sul tuo sito)
ma evidentemente ho sbagliato qualcosa. La classe di cui ho postato il
codice dovrebbe
essere quella che disaccoppia la gestione del segnale dall'invio del segnale
stesso
(nelle tue pagine è chaimata SignalQueee) . Nelle righe
// fa qualcosa con l'oggetto vector c'è semplicemente
// X x=(X)vector.remove(0);
// listener.recieve(X)
(esiste un solo ascoltatore di segnali)
Puoi darmi qualche consiglio su come realizzare la classe "di
disaccoppiamento"
(nel mio caso di listener  unico dovrebbe essere molto semplice )
che risolva il problema  senza effettuare il "busy waiting"?
(Ne ho un disperato bisogno per la tesi !!!!)
Grazie di nuovo Angelo

 scorra automaticamente in modo da farmi vedere le ultime righe
inserite?
Alla fine di un append:
textArea.setCaretPosition(textArea.getText().length());
;)

disaccoppiamento"
Ci posso provare. :-)
La signal queue normalmente e' in sleep, ovvero in attesa "non busy" - non 
occupa tempo macchina. Quindi la prima istruzione del ciclo e' (in 
pseudocodice) e' proprio una sleep:
while(! shutdown) {
  sleep();
  ...
}
Quando la sorgente vuole inviare un segnale (o evento), invoca un metodo della 
coda che fa due cose: 
- mette l'oggetto in lista (nella "coda" vera e propria cioe')
- sveglia il tread
Chiamiamo questo metodo "notify". notify e' invocato nel thread chiamante - 
quindi e' importante che sia efficiente e non bloccante. Efficiente lo e', 
perche' non fa nulla di piu' che inserire un riferimento ad un oggetto 
(l'evento) in coda, e poi invocare la primitiva interrupt() sul thread-coda, 
che viene svegliato, il che e' per definizione non bloccante. A questo punto il 
controllo, nel thread della sorgente (che puo' essere il thread principale o 
un'altro), ritorna alla sorgente stessa che va tranquillamente avanti:
notify(Signal s) {
  queue.put(s);    	    
  this.interrupt();
}
A questo punto, il thread-coda si e' svegliato, quindi passa ad eseguire le 
istruzioni dopo la sleep(). Che ovviamente non fanno altro che 
 - leggere il primo elemento della coda (che di norma e' una FIFO)
 - invocare il metodo di notifica nel ricevente
Ecco quindi il corpo completo del thread:
while(!shutdown) {
 sleep();
 while(queue.hasElements()) {
    Signal s=queue.get();    	// Recupera il segnale
    receiver.signalOccurred(s); // Invoca il metodo del listener
 }
}
Il tuo unico ricevitore e' "receiver" - che risponde come vuole. Per esser 
sicuri che il listener abbia il metodo "signalOccurred" niente di meglio che 
definire la relativa interfaccia, e richiedere - per la costruzione del thread-
coda - le venga passato che un riferimento ad un oggetto che la implementa.
Quindi ecco 
 SignalQueue(Listener receiver) {
  this.receiver=receiver;
 }
"signalOccurred" e' chiamato nel thread-coda, quindi se per qualche motivo il 
ricevitore si blocca - blocca solo la coda, e non la sorgente, che e' il 
disaccoppiamento che cercavamo.
Quanto sopra vale per un solo ricevitore. Con molti ricevitori, le cose si 
complicano un filo - a seconda dei requisiti, puoi dover clonare l'oggetto 
segnale (come fa AWT) e attaccare una coda ad ogni listener registrato per 
garantire la mutua indipendenza (se un listener si blocca, ha effetto solo 
sulla *sua* coda di eventi, non su quella degli altri listener).
Ma dato che a te serve un unico ricevente, non ce ne preoccupiamo. :^)
Inoltre, devi garantire che "signalOccurred" (e il codice che ci sta sotto nel 
grafo di chiamate) sia rientrante oppure non venga mai chiamato direttamente 
nel thread del ricevente stesso - dato che viene chiamato dal thread-coda.
Se vuoi gestire questo "a monte", a prezzo di un minimo di overhead, puoi 
sincronizzare esplicitamente l'invocazione di signalOccurred nel thread-coda, 
*sul* ricevente, con
 ...
 synchronized(receiver) {
  receiver.signalOccurred(s);
 }
 ...
Altrimenti, dai la responabilita' di cio' a chi scrive il ricevente, che 
provvedera' a implementare signalOccurred come synchronized.
In Java c'e' qualche dettaglio (del tipo che sleep() va messa in una try..catch 
per rilevare l'interruzione) ma non dovrebbero essere un problema.


 textArea.setCaretPosition(textArea.getText().length());
Perfetto. Grazie per il consiglio

Ti ringrazio moltissimo per  l'aiuto.
Ciao  Angelo