Visualizzazione dei risultati da 1 a 8 su 8
  1. #1
    Utente di HTML.it
    Registrato dal
    Mar 2013
    Messaggi
    68

    Comunicazio e sincronizzazione fra thread

    Ciao a tutti, sto cercando di creare un thread che a sua volta continui a generare figli ( RichiestaId ), ogni figlio avrà un id che verra elaborato da elaborazioneMessaggio che dovrà inviare un array di 6 int

    codice:
    package connessione;
    import java.io.IOException;
    import java.net.Socket;
    import java.net.UnknownHostException;
    
    public class MyActivityRoot implements Runnable
    {
        private static Socket socket = new Socket();
        
        private static int[] bloccoDomanda = new int[6];
        private static int[] blocco = new int[6];
    
        private static ConnessioneSocket a = new ConnessioneSocket();
        private static RichiestaId r;
        ElaborazioneMessaggio e = new ElaborazioneMessaggio();
        
    
    	@Override
    	public void run() 
    	{
    		
    		try {
    			socket = a.aprireConnessione();
    		} catch (UnknownHostException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		int id;
        	Thread t;
        	for( int i=0; i<6; i++)
        	{
        		
            	id = e.getID;
            	r = new RichiestaId(socket, id, Costante.DUE*l.getMessagesDelay());
        		
        		t = new Thread(r);
            	t.start();
    
            	
            	System.out.println();
            	
            	try {
    				bloccoDomanda = extract();
    			} catch (InterruptedException e2) {
    				// TODO Auto-generated catch block
    				e2.printStackTrace();
    			}
            	
    
        		System.out.println();
        		bloccoDomanda = r.getBlocco();
        		
        		System.out.println("Risposta del Root ");
        		for(int k = 0; k<6; k++) System.out.print(bloccoDomanda[k]+" ");
        		System.out.println();   
        		
        		if (e.ControlloRisposta(id, bloccoDomanda)) System.out.println("Va tutto bene");
        		else System.out.println("C'è qualcosa che non va");
        		
        		try {
    				Thread.sleep(10000);
    			} catch (InterruptedException e1) {
    				// TODO Auto-generated catch block
    				e1.printStackTrace();
    			}
        		
        		
    
        		
        	}
    		
    	}
    
    
    	
    	protected int[] extract() throws InterruptedException 
    	{
            synchronized (blocco)
            {
                blocco.wait(5000);
                return blocco;
            }
        }
    	
    	
        public void insert (int[] risposta)
        {
            synchronized (blocco) 
            {
                blocco = risposta;
                blocco.notifyAll();
            }
        }
    	
    
    	class RichiestaId implements Runnable 
    	{
    
    		private int id;
    		private Socket socket = new Socket();
    		private Comunicazione comunicazione = new Comunicazione();
    		private int[] bloccoRisposta = new int[Costante.N_BLOCCHI];
    		private int timeSleep;
    		
    		public RichiestaId(Socket socket, int id, int timeSleep)
    		{
    			this.id = id;
    			this.socket = socket;
    			this.timeSleep = timeSleep;
    		}
    		
    		public void run() 
    		{
    			
    			try {
    				comunicazione.invioID(id, socket);
    				try {
    					bloccoRisposta = comunicazione.ricezioneBloccoDati(socket);
    					insert(bloccoRisposta);
    					
    					System.out.print("Risposta\n");
    					System.out.println("2");
    					for(int i=0; i<6; i++)
    					{
    						System.out.print(bloccoRisposta[i]+" ");
    					}
    					notify();
    				} catch (IOException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    				
    				
    			} catch (IOException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    			
    			
    			System.out.println();
    			try {
    				Thread.sleep(timeSleep);
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    
    		
    		public int[] getBlocco() 
    		{
    			return bloccoRisposta;
    		}
    	}
    }
    ora il mio scopo è che il padre crei un figlio, attende che gli arrivi la risposta e se nel caso non gli arrivasse niente lo killa o si killa da solo dopo 5 secondi, dopo aspetta 10 secondi e crea il secondo figlio.
    purtroppo non riesco a sincronizzarli, non rispettano i tempi e ricevo i seguenti errori
    codice:
    Exception in thread "Thread-2" java.lang.IllegalMonitorStateException at java.lang.Object.notifyAll(Native Method)
    at connessione.MyActivityRoot.insert(MyActivityRoot.java:105) 
    at connessione.MyActivityRoot$RichiestaId.run(MyActivityRoot.java:138) 
    at java.lang.Thread.run(Unknown Source)
    credo di aver implementato male la sincronizzazione, tutto questo è all'interno di una stessa classe. Qualcuno può aiutarmi?

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Alcune cose:
    a) Hai usato tue classi come ConnessioneSocket e Comunicazione, che non hai postato e quindi non sappiamo cosa fanno di preciso (sì, beh, più o meno si intuisce comunque).

    b) Vedo "troppi" campi "di classe", ovvero static e questo personalmente non mi piace, perché in genere vuol dire che non stai usando bene gli oggetti incapsulando appropriatamente le cose.

    c) Da quanto vedo, uno stesso Socket viene usato da più thread e questa non mi pare una bella cosa.

    d) Vedo cose del tipo:
    comunicazione.ricezioneBloccoDati(socket);

    Anche qui dal punto di vista del design fa un po' "acqua". Non è bello passare un socket a qualcosa per leggere dei dati. Dovrebbe essere il contrario: un oggetto che ha il Socket (e prende/usa i suoi stream) e offre magari metodi per leggere qualcosa.

    e) Ci sono comunque problemi di sincronizzazione: un wait/notify/notifyAll va invocato solo su un oggetto di cui il thread corrente possiede il lock. Se il thread A invoca xyz.wait(), allora il thread A deve possedere il lock dell'oggetto referenziato da xyz. La regola è questa e non può essere disattesa.

    Nel run() del Runnable c'è un notify() che è invocato sul this ovvero appunto sulla istanza del Runnable. Non so a cosa ti serva, visto che non vedo un corrispettivo wait() sempre su quella stessa istanza del Runnable. E comunque in quel punto del notify() il thread non possiede certo il lock (non vedo nulla a riguardo) sul this. Quindi lì sicuramente fallisce.


    Insomma .... manca parecchio, anche a livello concettuale.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Utente di HTML.it
    Registrato dal
    Mar 2013
    Messaggi
    68
    ho capito più o meno tutti, tranne per cosa intendi per lock, un wait() non è un lock?

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da Maxton
    ho capito più o meno tutti, tranne per cosa intendi per lock, un wait() non è un lock?
    No, ogni oggetto possiede un "lock" (intrinsic lock e nella documentazione più tecnica è chiamato object's monitor). Che può essere acquisito da un solo thread per volta (da qui appunto l'effetto della mutua-esclusione tra thread).
    Il lock dell'oggetto lo si acquisisce solo usando la parola chiave synchronized (applicato a un metodo o a un blocco).

    I wait/notify agiscono sulla condition queue associata al lock. Ossia c'è una "coda" in cui più thread possono stare in attesa di essere "svegliati".
    Quando si esegue il wait(), il thread va in wait ma allo stesso tempo rilascia il lock. Quando esce dal wait(), allora compete di nuovo per riottenere il lock. E il problema è che per questioni interne alla JVM è possibile avere risvegli "spurii" e per tale motivo in genere il wait() si mette in un while che controlla una certa condizione (es. pensa ad una coda "sincronizzata" e "bloccante", il get si blocca finché la coda è vuota, cioè: while (codaVuota) fai il wait).
    Quindi il tuo modo di usare il wait non è nemmeno appropriato al 100%.

    E comunque se si fa un wait su un reference xyz, il/i notify vanno fatti su quello stesso identico reference, non su un altro.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  5. #5
    Utente di HTML.it
    Registrato dal
    Mar 2013
    Messaggi
    68
    ho capito il concetto ma non come scriverlo, mi faresti un esempio? anche semplice

  6. #6
    Utente di HTML.it
    Registrato dal
    Mar 2013
    Messaggi
    68
    come mi consigli di fare per evitare i campi static?

  7. #7
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da Maxton
    ho capito il concetto ma non come scriverlo, mi faresti un esempio? anche semplice
    Potrei farti l'esempio di una semplicissima coda sincronizzata/bloccante ... ma sarebbe forse oltremodo off-topic.

    E comunque, non voglio demoralizzarti/criticarti, ma ho l'impressione che ti manchino delle basi su thread e sincronizzazione.

    Originariamente inviato da Maxton
    come mi consigli di fare per evitare i campi static?
    Devi ripensare la applicazione valutando meglio le varie entità che sono in gioco e incapsulare meglio dati e comportamenti seguendo perlomeno i principali principi della OOP.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  8. #8
    Utente di HTML.it
    Registrato dal
    Mar 2013
    Messaggi
    68
    non mi demoralizzi affatto, questa è la mia prima esperienza con i thread. Provo a sistemare il codice con i consigli che mi hai dato. grazie mille...

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.