Thread

di il
39 risposte

Thread

Ciao ragazzi, vi contatto perchè ho del codice freaco da mostrare e chiedere un Vostro parere.
Premetto che é un codice scopiazzato e non capisco però cosa accade?

public class Synch {
public static void main(String[] args) {
// TODO Auto-generated method stub
CallMe target = new CallMe();
new Caller(target, "Hello");
new Caller(target, "Synchronized");
new Caller(target, "World");
} }

public class Caller implements Runnable {
private String msg;
private CallMe target;
public Caller(CallMe t, String s) {
target = t;
msg = s;
new Thread(this).start();
}
public void run() {
// TODO Auto-generated method stub
//synchronized(target){
target.call(msg);
//}
}
}
public class CallMe {
/*synchronized*/ public void call(String msg) {
System.out.print("[" + msg);
try {
Thread.sleep(1000);
}
catch (Exception e){}
System.out.println("]");
}
}
Output senza sincronizzazione Output con sincronizzazione
[Hello[Synchronized[World] [Hello]
] [Synchronized]
] [World]

39 Risposte

  • Re: Thread

    Ora cosa é successo!!!
    a me da come risultato output quello non sincronizzato

    come si fa a passare a quello sincronizzato?
  • Re: Thread

    Michele Genchi ha scritto:


    Ciao ragazzi, vi contatto perchè ho del codice freaco da mostrare e chiedere un Vostro parere.
    Premetto che é un codice scopiazzato e non capisco però cosa accade?
    La questione è questa: ci sono 3 thread e c'è un oggetto "condiviso" che è facile da vedere e capire perché lo stesso oggetto CallMe viene passato ai tre oggetti Caller.

    Il run() del thread fa nient'altro che invocare call sul CallMe condiviso. E il call del CallMe stampa il messaggio, attende un po' e poi stampa "]".

    Ora, senza alcun tipo di accorgimento, siccome la esecuzione e le tempistiche dei thread sono molto aleatorie e dipendono da molti fattori, allora può capitare che i tre messaggi vengano stampati in qualunque ordine e pure che i due print/println siano "intermixati" tra i thread.

    Ovvero es.:

    print di "[Hello"
    print di "[World"
    println di "]" (relativo al thread di Hello)
    println di "]" (relativo al thread di World)

    Michele Genchi ha scritto:


    come si fa a passare a quello sincronizzato?
    Dipende sincronizzato per ottenere che cosa. Non basta dire solo "sincronizzato".

    Se il tuo interesse è far in modo che [messaggio] venga stampato così per intero senza alcun disturbo tra i vari thread, allora è sufficiente rendere "atomico" il call(). E questo si può fare ottenendo il lock (da parte di ciascun thread per volta) sull'oggetto condiviso che è il CallMe.
    Quindi si può rendere call synchronized oppure acquisire esplicitamente il lock sul target.

    Che è appunto la parte commentata.

    Se invece intendi ottenere una certa sequenzialità particolare (es. che [Hello] venga sempre stampato prima di [Synchronized]), allora è un altro discorso. E non basta un banale synchronized.
  • Re: Thread

    Sincronizzato
    [Hello]
    [Synchronized]
    [World]
  • Re: Thread

    Michele Genchi ha scritto:


    sincronizzato
    [Hello]
    [Synchronized]
    [World]
    Se call è solo "atomico" anche questo output

    [World]
    [Synchronized]
    [Hello]

    è possibile. O qualunque altra sequenza.
  • Re: Thread

    Sul libro che sto studiando c'era quel codice e come output dava:
    sincronizzato
    [Hello]
    [Synchronized]
    [World]
    Non sincronizzato
    [Hello[Synchronized[World]
    ]
    ]

    Copiato ed incollato, a me da come output solo il non sincronizzato.
    L'altro me lo da se faccio il debug
  • Re: Thread

    Michele Genchi ha scritto:


    Copiato ed incollato, a me da come output solo il non sincronizzato.
    L'altro me lo da se faccio il debug
    Ti ripeto (l'ho detto prima), che se vuoi solo aver call() "atomico", è sufficiente:

    il synchronized sul metodo call
    O
    il synchronized(target) al blocco che invoca call.

    E queste sono appunto le parti "commentate" del codice.
  • Re: Thread

    Okay, ho capito ora, grazie
  • Re: Thread

    Grazie al tuo suggerimento e aiuto ho capito bene il thread e l'ho applicato ad un giochino di dadi
  • Re: Thread

    Si continua con lo studio, adesso sto facendo i metodi wait e notify della classe thread
    Ed ho pensato di fare una simulazione di un semaforo per eaercitazione... Che mi dite? È fattibile? e che suggerimenti avete in merito?
    Volevo tenere pronti i tre colori del semaforo e mettere in pausa i colori spenti... Mmmh veramente volevo arrivarci da solo, ma qlk piccolo consiglio è bene accetto
  • Re: Thread

    Michele Genchi ha scritto:


    adesso sto facendo i metodi wait e notify della classe thread
    Nota che wait/notify/notifyAll sono di Object, ovvero qualunque oggetto li ha.

    Michele Genchi ha scritto:


    Ed ho pensato di fare una simulazione di un semaforo per eaercitazione... Che mi dite? È fattibile? e che suggerimenti avete in merito?
    Volevo tenere pronti i tre colori del semaforo e mettere in pausa i colori spenti... Mmmh veramente volevo arrivarci da solo, ma qlk piccolo consiglio è bene accetto
    Sì, è possibile. Ma prima magari fai un esercizio interessante.
    Nel codice sopra, anche se usi il synchronized le stringhe Hello Synchronized World possono essere stampate in qualunque ordine. Il synchronized garantisce solo atomicità e mutua esclusione. Non garantisce nulla sulla sequenzialità dei thread.
    Usa wait/notifyAll per assicurare una certa sequenza delle scritte.
  • Re: Thread

    Si caro, hai ragione object, e sono ereditate da tutte le sottoclassi, cmq in questo caso; correggimi se sbaglio, è applicato alla classe thread...
    Okay come primo esercizio modificò quello che hai detto tu e magari do una ricontrollato al gioco dei dadi...
    Mmmh ma almeno sto migliorando o devo cambiare mestiere?
  • Re: Thread

    SCJP 5 (91%) – SCWCD 5 (94%)
    complimenti Andrea , ecco perché sentivo di parlare con una persona preparata,
    a volte ho paura però a confrontarmi con persone come te

    ho provato l'esercizio che mi hai detto:
    public class CallMe {
    boolean pausa;
    synchronized public void call(String msg,boolean p) {
    pausa=p;
    System.out.print("[" + msg);
    if (!pausa)
    try {
    Thread.sleep(2000);
    System.out.println("]");
    pausa=true;
    wait(); }
    catch (Exception e){}
    else { notifyAll(); }
    }
    }
    In fase di debug cerco di capire cosa accade !!! ma non risulta granché
  • Re: Thread

    Michele Genchi ha scritto:


    Si caro, hai ragione object, e sono ereditate da tutte le sottoclassi, cmq in questo caso; correggimi se sbaglio, è applicato alla classe thread...
    No, non c'entra direttamente con un java.lang.Thread, cioè non c'è nulla di speciale nel suo riguardo. wait/notify/notifyAll sono di qualunque oggetto. Anche un oggetto java.lang.Thread alla fin fine .. è un oggetto, quindi anche su di esso si può acquisire il lock e poi usare i 3 metodi citati. (io però non andrei mai ad usare un java.lang.Thread come lock/condition-queue)

    Michele Genchi ha scritto:


    public class CallMe {
    boolean pausa;
    	synchronized public void call(String msg,boolean p) {
    		pausa=p;
    		System.out.print("[" + msg);
    			if (!pausa) 
    				try {
    					Thread.sleep(2000);
    					System.out.println("]");
    					pausa=true;
    					wait();				}
    				catch (Exception e){}
    			else { notifyAll(); }
    	}
    }
    No, non basta (e non è nemmeno proprio corretto) per imporre una sequenzialità ai thread in modo da stampare i messaggi in un ben preciso ordine.

    Ci sono (sicuramente) diversi modi di realizzare questa cosa. Ne dico giusto uno:

    Si può dare agli oggetti Caller un numero progressivo, es. il primo Caller 0, il secondo 1, ecc...
    Poi in CallMe si mette una variabile di istanza che tiene il numero relativo al Caller che deve essere lasciato "passare" per stampare il messaggio.
    Poi quando in Caller invochi il call di CallMe, oltre a passare il messaggio passi anche il numero del Caller.
    Se in CallMe il numero da lasciar passare è 0, vuol dire che il Caller 0 deve poter stampare il messaggio mentre gli altri Caller (anche se dovessero arrivare prima in quel punto) devono bloccarsi e stare in attesa.
    Una volta stampato il messaggio, incrementi il numero (in modo che il Caller successivo possa passare) e fai notifyAll().

    Ricordati che il wait() andrebbe sempre fatto dentro un ciclo (tipicamente un while) che deve testare una condizione che è quella che deve "reggere" affinché il thread stia in attesa.

    Prova con queste indicazioni.
  • Re: Thread

    Okay grazie, per il simulatore del semaforo aspetto, faccio prima questo... Anche perché simulare 4 semafori ad un incrocio è complicato...
Devi accedere o registrarti per scrivere nel forum
39 risposte