Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Sony WF-1000X M6: le cuffie in-ear di riferimento migliorano ancora
Sony WF-1000X M6: le cuffie in-ear di riferimento migliorano ancora
WF-1000X M6 è la sesta generazione di auricolare in-ear sviluppata da Sony, un prodotto che punta a coniugare facilità di utilizzo con una elevata qualità di riproduzione dei contenuti audio e una cura nella riduzione del rumore ambientale che sia da riferimento
Snowflake porta l'IA dove sono i dati, anche grazie a un accordo con OpenAI
Snowflake porta l'IA dove sono i dati, anche grazie a un accordo con OpenAI
Snowflake ha presentato diverse novità per la sua piattaforma legate all'intelligenza artificiale. Quella forse più eclatante è una collaborazione con OpenAI, ma non mancano diverse nuove funzionalità che rendono la piattaforma più flessibile e in grado di rispondere meglio alle esigenze in continuo cambiamento delle aziende
Sistema Mesh Roamii BE Pro: il Wi-Fi 7 secondo MSI
Sistema Mesh Roamii BE Pro: il Wi-Fi 7 secondo MSI
Con velocità teoriche fino a 11 Gbps, gestione tramite app intelligente e protezione avanzata dei dispositivi, Roamii BE Pro porta il Wi‑Fi 7 tri‑band nelle abitazioni più esigenti. Un sistema Wi-Fi Mesh proposto da MSI allo scopo di garantire agli utenti una rete fluida e continua capace di sostenere streaming 8K, gaming competitivo e le applicazioni moderne più esigenti in termini di banda
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 25-02-2007, 17: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, 22: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, 11: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, 13: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, 13: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, 18: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, 19: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, 19: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, 19: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, 20: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, 21: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, 21: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, 22: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, 10: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, 13: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, 14: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, 15: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, 17: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, 10: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, 10: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


Sony WF-1000X M6: le cuffie in-ear di riferimento migliorano ancora Sony WF-1000X M6: le cuffie in-ear di riferiment...
Snowflake porta l'IA dove sono i dati, anche grazie a un accordo con OpenAI Snowflake porta l'IA dove sono i dati, anche gra...
Sistema Mesh Roamii BE Pro: il Wi-Fi 7 secondo MSI Sistema Mesh Roamii BE Pro: il Wi-Fi 7 secondo M...
Recensione HUAWEI Mate X7: un foldable ottimo, ma restano i soliti problemi Recensione HUAWEI Mate X7: un foldable ottimo, m...
Nioh 3: souls-like punitivo e Action RPG Nioh 3: souls-like punitivo e Action RPG
Roscosmos ha lanciato il satellite meteo...
Starship Troopers: Ultimate Bug Wars, to...
Il razzo spaziale europeo Ariane 6, per ...
Oracle Fusion Cloud Applications si pote...
OHB Italia svilupperà un satellit...
Fortinet: "Ora abbiamo una chance d...
Linux Mint chiude con gli aggiornamenti ...
Compressori portatili auto in sconto su ...
Durante il lancio della missione USSF-87...
Dopo il ritiro di Intel da Magdeburgo, l...
Xiaomi 15T scende a 388€ su Amazon: 12GB...
MSI Afterburner: arriva il monitoraggio ...
Missione cinese Chang'e-6: confermata l'...
Addio esenzione sotto i 150 euro: l'UE i...
Allarme riavvii su Windows 11 dopo il ri...
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: 20:25.


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