Torna indietro   Hardware Upgrade Forum > Software > Programmazione

iPhone 17 Pro: più di uno smartphone. È uno studio di produzione in formato tascabile
iPhone 17 Pro: più di uno smartphone. È uno studio di produzione in formato tascabile
C'è tanta sostanza nel nuovo smartphone della Mela dedicato ai creator digitali. Nuovo telaio in alluminio, sistema di raffreddamento vapor chamber e tre fotocamere da 48 megapixel: non è un semplice smartphone, ma uno studio di produzione digitale on-the-go
Intel Panther Lake: i processori per i notebook del 2026
Intel Panther Lake: i processori per i notebook del 2026
Panther Lake è il nome in codice della prossima generazione di processori Intel Core Ultra, che vedremo al debutto da inizio 2026 nei notebook e nei sistemi desktop più compatti. Nuovi core, nuove GPU e soprattutto una struttura a tile che vede per la prima volta l'utilizzo della tecnologia produttiva Intel 18A: tanta potenza in più, ma senza perdere in efficienza
Intel Xeon 6+: è tempo di Clearwater Forest
Intel Xeon 6+: è tempo di Clearwater Forest
Intel ha annunciato la prossima generazione di processori Xeon dotati di E-Core, quelli per la massima efficienza energetica e densità di elaborazione. Grazie al processo produttivo Intel 18A, i core passano a un massimo di 288 per ogni socket, con aumento della potenza di calcolo e dell'efficienza complessiva.
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 25-02-2007, 16:15   #1
lovaz
Senior Member
 
L'Avatar di lovaz
 
Iscritto dal: Jul 2002
Messaggi: 4334
[JAVA] Worker thread, giusto così?

Salve,

devo fare un update di un componente swing - setText o setIcon - con dei
dati che impiego un po' a calcolare, e quindi devo tirare via la computazione
dall'EDT, pena "freeze" della gui.

C'è anche da dire che se durante l'esecuzione del worker thread ne lancio un altro
voglio che sia quest'ultimo ad aggiornare il componente.
In pratica le vecchie computazioni non mi interessano.

Ho impostato la classe così:
Codice:
public class IDTextUpdater
	implements Runnable
{
	...
	private static Thread lastThread;
	...

/* qui sono nel costruttore */
		// update last thread variable
		lastThread = new Thread(this);
		lastThread.start();
/* fine costruttore */

/* nel metodo run()... */
		// lavora...
		...
		if( lastThread != Thread.currentThread() )
			return;

		// aggiorna il componente
		SwingUtilities.invokeLater( new Runnable() {...} )
/* fine run() */
Il tutto sembra funzionare egregiamente, ma siccome con la concorrenza
non si sa mai, vedete qualcosa che potrebbe non andare?

Grazie.
lovaz è offline   Rispondi citando il messaggio o parte di esso
Old 25-02-2007, 21:08   #2
thebol
Senior Member
 
Iscritto dal: Dec 2000
Città: bologna
Messaggi: 1309
se la computazione è grossa nel costruttore potresti mettere uno stop thread(nn ricordo se è deprecato, cmq bloccarlo in qualche maniera).

Cmq se per caso viene creato un nuovo updater, e il vecchio è bloccato dopo il controllo if( lastThread != Thread.currentThread() ), e il nuovo updater finisce prima che il controllo ritorni al vecchio updater, puoi trovarti con la textbox valorizzata col risultato del vecchio updater.
thebol è offline   Rispondi citando il messaggio o parte di esso
Old 26-02-2007, 10:50   #3
lovaz
Senior Member
 
L'Avatar di lovaz
 
Iscritto dal: Jul 2002
Messaggi: 4334
Grazie della risposta.

Sì, stop è deprecato, il modo pulito per terminare un thread è uscire dal metodo run().

Per il resto forse hai ragione, ma d'altra parte non saprei come fare diversamente...

Forse mettendo statici i componenti da aggiornare e mettendoli a null
nel costruttore? Il tutto sincronizzato ovviamente.
lovaz è offline   Rispondi citando il messaggio o parte di esso
Old 26-02-2007, 12:10   #4
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
lastThread deve essere volatile o incapsulato in un AtomicReference.

Come indicato da thebol, il programma che hai scritto non fa quello che vorresti (eseguire solo l'ultimo aggiornamento grafico). Tra le possibili soluzioni io vedrei bene una doppia coda di consumazione di eventi Runnable. Una per le computazioni in background, una per gli aggiornamento grafici. Quando immetti una computazione, che potrebbe essere rappresentata con;

Codice:
interface MultiTask {
    Runnable getBackgroundTask();
    Runnable getAWTTask();
}
infili nella coda dei compiti in background il prodotto di getBackgroundTask(), svuoti la coda dei compiti AWT e immetti il prodotto di getAWTTask(). L'uso di una coda (LinkedBlockingQueue) garantisce la sequenzialità dell'esecuzione di compiti AWT non più annullabili (già offerti prima di un clear()). Lo stesso tipo di struttura dati per i compiti in background ti permette di delegare l'esecuzione degli stessi ad un pool di Thread, idealmente più efficiente di un Thread per computazione.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me!
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 26-02-2007, 12:29   #5
lovaz
Senior Member
 
L'Avatar di lovaz
 
Iscritto dal: Jul 2002
Messaggi: 4334
Ok, ci lavoro su e vi faccio sapere.
lovaz è offline   Rispondi citando il messaggio o parte di esso
Old 26-02-2007, 17:56   #6
lovaz
Senior Member
 
L'Avatar di lovaz
 
Iscritto dal: Jul 2002
Messaggi: 4334
Allora, per i thread pool e le code bloccanti vedrò più avanti,
magari li userò per un altra cosetta che ho in mente.

Intanto ho modificato il codice così:
Codice:
	private static IDTextUpdater lastUpdater; // tolto lastThread
	private boolean stopped;
	...
/* qui sono nel costruttore */
		this.stopped = false;
		
		if( lastUpdater != null )
			lastUpdater.stop();
		
		lastUpdater = this;
		new Thread( this ).start();
/* fine costruttore */

	void stop()
	{
		stopped = true;
	}

/* nel metodo run()... */
		// lavora...
		...
		if( stopped )
			return;

		SwingUtilities.invokeLater( new Runnable()
			{ if( !stopped ) /* update componente*/...} );
/* fine run() */
Che ne dite?
lovaz è offline   Rispondi citando il messaggio o parte di esso
Old 26-02-2007, 18:12   #7
^TiGeRShArK^
Senior Member
 
L'Avatar di ^TiGeRShArK^
 
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
e xkè non usare SwingWorker anzikè reinventare la ruota?
ehm...
ovviamente se epuoi usare java 6
__________________
^TiGeRShArK^ è offline   Rispondi citando il messaggio o parte di esso
Old 26-02-2007, 18:17   #8
lovaz
Senior Member
 
L'Avatar di lovaz
 
Iscritto dal: Jul 2002
Messaggi: 4334
Devo usare java5, e comunque non risparmierei una riga di codice...
lovaz è offline   Rispondi citando il messaggio o parte di esso
Old 26-02-2007, 18:35   #9
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
non potendo essere final, lastUpdater e stopper devono essere volatile o incapsulati in un AtomicReference/AtomicBoolean o il loro accesso deve essere contenuto in un blocco sincronizzato.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me!
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 26-02-2007, 19:39   #10
thebol
Senior Member
 
Iscritto dal: Dec 2000
Città: bologna
Messaggi: 1309
Quote:
Originariamente inviato da PGI-Bis Guarda i messaggi
non potendo essere final, lastUpdater e stopper devono essere volatile o incapsulati in un AtomicReference/AtomicBoolean o il loro accesso deve essere contenuto in un blocco sincronizzato.
*
in quella maniera hai solo spostato piu avanti nel codice il controllo, ma non l'hai eliminato o reso sincronizzato rispetto a piu thread.

ps che roba sono le atomicQualcosa?
thebol è offline   Rispondi citando il messaggio o parte di esso
Old 26-02-2007, 20:36   #11
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Sono i nuovi volatile. Se prima si diceva:

private volatile boolean pimpumpam...

oggi si dovrebbe prediligere:

private final AtomicBoolean pimpumpam...

C'è un Atomic per tipo, con AtomicReference asso piglia tutto.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me!
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 26-02-2007, 20:56   #12
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Credo che il problema d'ordine sia stato risolto. Quel booleano, uno per ogni Thread, viene controllato in un unico Thread, l'AWT Event Dispatcher. Poichè il Runnable è premuto nella coda degli eventi AWT, esiste una relazione d'ordine tra gli eventi.

Se il Thread è bloccato nell'esecuzione del runnable allora non può verificarsi l'aggiornamento grafico del Thread successivo perchè il Thread successivo ha premuto il suo evento nella stessa coda.

Se l'evento del Thread precedente è premuto nella coda prima di quello del Thread successivo, allora quando sarà eseguito il runnable del Thread precedente il valore di stopped sarà necessariamente (volatile o Atomic) true.

Insomma, mi pare che funzioni. A naso e alla 22:00, ma direi che funziona. Lì. Quello che mi lascia perplesso è "lastUpdater".

E' possibile che un Thread a cui è affidata l'esecuzione di un aggiornamento precedente arrivi a bloccare un Thread a cui è affidata l'esecuzione dell'aggiornamneto successivo.

io eseguo:

thread 1 (aggiornamento ui vecchio) -> via
thread 2 (aggiornamento ui nuovo) -> via

thread 1 sta per eseguire: lastUpdater.stop

thread 2 tira la volata e arriva fino a lastUpdater = this
thread 1 esegue lastUpdate.stop e impedisce l'aggiornamento UI di Thread 2

L'ultimo aggiornamento grafico non viene eseguito.

O mi sono perso qualcosa?
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me!
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 26-02-2007, 21:19   #13
thebol
Senior Member
 
Iscritto dal: Dec 2000
Città: bologna
Messaggi: 1309
Quote:
Originariamente inviato da PGI-Bis Guarda i messaggi
Credo che il problema d'ordine sia stato risolto. Quel booleano, uno per ogni Thread, viene controllato in un unico Thread, l'AWT Event Dispatcher. Poichè il Runnable è premuto nella coda degli eventi AWT, esiste una relazione d'ordine tra gli eventi.

Se il Thread è bloccato nell'esecuzione del runnable allora non può verificarsi l'aggiornamento grafico del Thread successivo perchè il Thread successivo ha premuto il suo evento nella stessa coda.

Se l'evento del Thread precedente è premuto nella coda prima di quello del Thread successivo, allora quando sarà eseguito il runnable del Thread precedente il valore di stopped sarà necessariamente (volatile o Atomic) true.

Insomma, mi pare che funzioni. A naso e alla 22:00, ma direi che funziona. Lì.

si avevo letto troppo velocemente il codice, mi sa che hai ragione tu

Quote:
Quello che mi lascia perplesso è "lastUpdater".

E' possibile che un Thread a cui è affidata l'esecuzione di un aggiornamento precedente arrivi a bloccare un Thread a cui è affidata l'esecuzione dell'aggiornamneto successivo.

io eseguo:

thread 1 (aggiornamento ui vecchio) -> via
thread 2 (aggiornamento ui nuovo) -> via

thread 1 sta per eseguire: lastUpdater.stop

thread 2 tira la volata e arriva fino a lastUpdater = this
thread 1 esegue lastUpdate.stop e impedisce l'aggiornamento UI di Thread 2

L'ultimo aggiornamento grafico non viene eseguito.

O mi sono perso qualcosa?
mi sa che hai ragione...

...tanto per far capire quanto sia complicato giocare con i thread
thebol è offline   Rispondi citando il messaggio o parte di esso
Old 27-02-2007, 09:13   #14
lovaz
Senior Member
 
L'Avatar di lovaz
 
Iscritto dal: Jul 2002
Messaggi: 4334
Ma ragazzi, il costruttore, in cui chiamo lastUpdater.stop(), viene eseguito nell'EDT,
che e' un unico thread, quindi sequenzialmente, e non parallelamente, o sbaglio?

lastUpdater non e' un thread, e' un Runnable eseguito dal thread.
lovaz è offline   Rispondi citando il messaggio o parte di esso
Old 27-02-2007, 12:40   #15
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Se lastUpdater ha un metodo stop è un po' più di un Runnable. Che non sia un Thread l'ho capito .

Se il costruttore è eseguito dall'AWT Event Dispatcher allora, contrariamente al classico libro giallo, la trama si semplifica.

Il caso che mi lasciava perplesso non si verifica più. lastUpdater non deve essere volatile/atomic: è usato da un solo Thread dunque che sia aggiornata la sola copia locale di quel campo è indifferente.

Deve ancora essere volatile/atomic "stopped", perchè il suo valore è letto da un Thread e scritto da un altro.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me!
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 27-02-2007, 13:17   #16
lovaz
Senior Member
 
L'Avatar di lovaz
 
Iscritto dal: Jul 2002
Messaggi: 4334
Ma l'assegnamento a un boolean e' comunque atomico... o no?
lovaz è offline   Rispondi citando il messaggio o parte di esso
Old 27-02-2007, 14:06   #17
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
E' un inghippo terminologico. Sì, l'assegnamento è atomico, nello stesso senso in cui non è atomico l'assegnamento ad un long.

Ma se portiamo la faccenda in un contesto concorrente, questa atomicità non è più sufficiente. I thread operano su copie locali dei campi. Tutte le operazioni che un Thread esegue su un campo sono operazioni il cui effetto è limitato alla copia locale di quel campo. Così se in un Thread assegno al campo ciccio il valore N ciò che accade, secondo le specifiche del linguaggio, è che la copia locale del campo ciccio, che esiste solo per quel tal Thread, assume il valore N. Il campo "vero", quello che esiste nell'heap, resta inalterato. Lo stesso vale per la lettura. Quando un Thread legge il valore di un campo legge il valore della copia locale di quel campo.

I valori iniziali dei campi usati dai Thread sono quelli esistenti nell'heap. Poichè ogni volta che un Thread muta il valore di un campo tale mutazione è propria della sola copia locale di quel campo, in linea di principio i campi hanno sempre e solo il valore iniziale predefinito (null per i reference, 0 per i numerici, '\0' per i caratteri, false per i boolean).

Ci sono poi una serie di norme che stabiliscono quando la manipolazione che un Thread opera su un campo risulta visibile ad altri Thread. Una di queste coinvolge l'uso del modificatore volatile (e del suo alter-ego in Java 5 rappresentato dagli AtomicBlaBla). Detto terra-terra, quando assegni un valore ad un campo volatile quel valore finisce nell'heap e sarà quindi il valore ottenuto da altri Thread quando accederanno a quel campo.

Nel nostro caso noi ci chiediamo: qual'è il valore del campo "stopped". Basandoci sulle norme del modello di memoria del linguaggio di programmazione Java noi sappiamo che.

1. stopped ha sicuramente il valore di inizializzazione predefinito "false".
2. nel costruttore quel valore cambia ma quello che veramente cambia è il valore di una copia locale (ad un Thread) di stopped.
3. nel metodo run, il valore certo di stopped è false se il run sia eseguito da un Thread diverso da quello che ha invocato il costruttore.
4. nel metodo run del Runnable usato in invokeLater, il valore certo di stopped è ancora false se il costruttore non sia stato eseguito dall'AWT Event Dispatcher. E' true se, come nel nostro caso, il costruttore sia stato eseguito dall'AWT Event Dispatcher.

Ecco perchè dico che "stopped" deve essere volatile: perchè il metodo run è certamente eseguito da un Thread diverso dall'AWT Event Dispatcher.

Non serve che sia volatile "lastUpdated". In questo caso, infatti, hai garantico che il costruttore, in cui il valore di lastUpdated cambia, sarà eseguito sempre e soltanto da un solo Thread. Questo Thread lavorerà sulla sua copia locale e questa copia locale assumerà di volta in volta valori diversi.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me!
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 27-02-2007, 16:00   #18
lovaz
Senior Member
 
L'Avatar di lovaz
 
Iscritto dal: Jul 2002
Messaggi: 4334
Ah, ok...
Grazie.
lovaz è offline   Rispondi citando il messaggio o parte di esso
Old 28-02-2007, 09:00   #19
lovaz
Senior Member
 
L'Avatar di lovaz
 
Iscritto dal: Jul 2002
Messaggi: 4334
Una curiosita': questa storia delle variabili locali ai thread vale anche per le statiche?
lovaz è offline   Rispondi citando il messaggio o parte di esso
Old 28-02-2007, 09:33   #20
thebol
Senior Member
 
Iscritto dal: Dec 2000
Città: bologna
Messaggi: 1309
a naso direi di si, ma aspetterei il guru per la conferma
thebol è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


iPhone 17 Pro: più di uno smartphone. È uno studio di produzione in formato tascabile iPhone 17 Pro: più di uno smartphone. &Eg...
Intel Panther Lake: i processori per i notebook del 2026 Intel Panther Lake: i processori per i notebook ...
Intel Xeon 6+: è tempo di Clearwater Forest Intel Xeon 6+: è tempo di Clearwater Fore...
4K a 160Hz o Full HD a 320Hz? Titan Army P2712V, a un prezzo molto basso 4K a 160Hz o Full HD a 320Hz? Titan Army P2712V,...
Recensione Google Pixel Watch 4: basta sollevarlo e si ha Gemini sempre al polso Recensione Google Pixel Watch 4: basta sollevarl...
Samsung è sempre più prota...
ChatGPT ha pregiudizi politici? Ecco cos...
Un solo iPhone rubato ha portato alla sc...
Xiaomi 17 Ultra sta arrivando: ecco come...
Il Motorola Edge 70 non ha più se...
Alcuni Galaxy S26 utilizzeranno il chip ...
Amazon, ecco i super sconti del weekend:...
Scovare un bug di sicurezza sui disposit...
Offerta Amazon su NordVPN: proteggi 10 d...
ECOVACS DEEBOT X8 PRO OMNI in offerta su...
Scope elettriche Tineco in offerta su Am...
Offerta Amazon sui robot EUREKA J15 Ultr...
Chrome disattiverà automaticament...
Tornano tutti e 4 i colori disponibili p...
Super sconto su iPhone 16: Amazon abbass...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 04:28.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Served by www3v