Visualizzazione dei risultati da 1 a 7 su 7
  1. #1
    Utente di HTML.it
    Registrato dal
    Oct 2002
    Messaggi
    7

    Aiuto Thread!!!

    Ciao a tutti, ho un problema con un compitino che devo fare e non riesco a trovare il bandolo della matassa.
    Mi é stato chiesto di utilizzare il seguente codice, per fare in pratica questo:
    Commander1 chiede una domanda (sempre per primo), e il soldato gli risponde e quindi va in Wait fino alla prossima domanda.
    Il programma sembra fgunzionare, ma se io cambio :
    il valore di Thread.sleep(500)
    oppure
    l'ordine delle chiamate in Main
    il programma non risponde piú (penso che entrambe le Thread vanno in Wait (nonostante il NotifyAll().).
    Aiuto devo consegnare il compitino e non trovo il bandolo... Grazie a tutti in anticipo per l'aiuto!
    Strider

    codice:
    //********************//
    
    public class soldatino_1 implements Runnable 
    {
         private final String[] ANSWERS = { "25", "2", "All of us are Sir!" };
         private int nextAnswer = 0;
         private comandante_1 mycomandante;
         
        public soldatino_1() 
        {
    //        super();
        }
        
        /** Second Constructor */
        public soldatino_1(comandante_1 c_1) 
        {
    //        super();
            mycomandante = c_1;
        }
    
         /** Sets the answer number */
        private synchronized void answerQuestion()
        {
            while(!mycomandante.isWaitingForAnswer())
            { 
                try
                {
                    wait();
                }
                catch(InterruptedException e)
                {
                    String errMessage = e.getMessage();
                    System.out.println(errMessage);
                }
            }        
            nextAnswer = mycomandante.getNextQuestion();
            mycomandante.sir(); 
            System.out.println("soldatino (A" + nextAnswer + "):" + ANSWERS[nextAnswer]);    
            notifyAll();            
        }
        
        /** Override the Run method*/
        public void run()
        {
            for(int i = 0; i <3; i++)
            {
                try
                {
                    Thread.sleep(500);
                }
                catch(InterruptedException e)
                {
                    String errMessage = e.getMessage();
                    System.out.println(errMessage);
                }                    
                answerQuestion();
            }
        }
    }
    
    //********************//
    
    import java.util.Random;
    
    public class comandante_1 extends Thread
    {
        private final String[] Questions = { "How old are you?", "How many fitness tests have you taken?", "Are you prepared for the war?" };
        private int nextQuestion = 0;
        private Random generator = new Random();
        private boolean waitingForAnswer = false;
        
        /** Creates a new instance of comandante */
        public comandante_1() 
        {
    //        super();
        }
        
        /** Returns an int value set randomly using the Random class */
        private int setNextQuestion()
        {
            int r = generator.nextInt(3);
            return r;
        }
        
        /** Sets the question number randomly using the setNextQuestion method */
        private synchronized void askQuestion()
        {           
            while(isWaitingForAnswer())
            {
                try
                {
                    wait();
                }
                catch(InterruptedException e)
                {
                    String errMessage = e.getMessage();
                    System.out.println(errMessage);
                }
            }
            nextQuestion = setNextQuestion();
            setWaitingForAnswer(true);
            System.out.println("comandante (Q" + nextQuestion + "):" + Questions[nextQuestion]);
            notifyAll();              
        }
        
        /** Override the Run method*/
        public void run()
        {
            for(int i = 0; i <3; i++)
            {            
                try
                {
                    Thread.sleep(500);
                }
                catch(InterruptedException e)
                {
                    String errMessage = e.getMessage();
                    System.out.println(errMessage);
                }                    
                askQuestion();
            }
        }
        
        // Private Setter method:
        private void setWaitingForAnswer(boolean b)
        {
            waitingForAnswer = b;
        }
        
        // Public method Sir:
        public void sir()
        {
            setWaitingForAnswer(false);
        }
        
        // Pubblic getter method:    
        public boolean isWaitingForAnswer()
        {
            return waitingForAnswer;
        }
            
        // Public method getNextQuestion:
        public int getNextQuestion()
        {
            return nextQuestion;
        }
    }
    
    //**************************//
    
    public class Main
    {
       public static void main(String[] args) 
       {    
           Comandante_1 com_1 = new Comandante_1();
           Soldatino_1 sol_1 = new Soldatino_1(com_1);
           Thread thre_1 = new Thread(sol_1);   
           
           com_1.start();
           thre_1.start();
    
       }   
    }
    Strider
    "Due cose sono infinite: l’universo e la stupidità umana, ma riguardo l’universo ho ancora dei dubbi." A.Einstein

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,254
    Guarda, non ho letto tutto il codice perchè è un po' lungo e non ho molto tempo. Posso però suggerirti di incapsulare tutta la logica di gestione della domanda/risposta in una apposita classe (es. con molta fantasia ... DomandaRisposta ) invece di sparpagliare la logica tra le due classi per comandante e soldatino (che non è il massimo).

    In pratica ti sto suggerendo di avere un oggetto DomandaRisposta che sarà "condiviso" dalle due entità e che potrebbe avere 3 metodi:

    String poniDomanda(String domanda).
    Che pone la domanda, sta in wait finché non arriva una risposta e quindi ritorna con la risposta.

    String leggiDomanda()
    Che sta in wait fino all'arrivo di una domanda quindi la restituisce.

    void rispondi(String risposta)
    Che risponde alla domanda facendo "risvegliare" il thread che ha invocato poniDomanda.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    Java Versions Cheat Sheet

  3. #3
    Utente di HTML.it
    Registrato dal
    Oct 2002
    Messaggi
    7
    Ciao andbin,
    innanzitutto grazie per l'aiuto, quindi le mie domande:
    scusa ma non ho ben capito. Io pensavo che assegnando com_1 come argomento a sol_1 in Main() e quindi passando la referenza a com_1 a mycomandante nel constructor di soldatino_1 le due Thread fossero indirizzate sullo stesso oggetto (mycomandante = comandante_1), dove sbaglio?
    Scusami ma sono alle prime armi e devo consegnare presto...
    Ciao
    Strider
    "Due cose sono infinite: l’universo e la stupidità umana, ma riguardo l’universo ho ancora dei dubbi." A.Einstein

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,254
    Originariamente inviato da strider
    Io pensavo che assegnando com_1 come argomento a sol_1 in Main() e quindi passando la referenza a com_1 a mycomandante nel constructor di soldatino_1 le due Thread fossero indirizzate sullo stesso oggetto (mycomandante = comandante_1), dove sbaglio?
    Che l'oggetto Soldatino_1 riceve (e si tiene dentro) un riferimento all'oggetto Comandante_1, su questo non ci sono dubbi e non ho nulla da ridire.

    Ma non è questo il punto. Il punto fondamentale è che l'oggetto su cui acquisire il "lock" deve essere lo stesso. Ma nel tuo codice non è così. In comandante_1 usi un metodo di istanza synchronized, quindi il lock è su sé stesso, ovvero l'oggetto comandante_1.
    Mentre in soldatino_1 usi un altro metodo di istanza anch'esso synchronized e il lock è pure su sé stesso, ovvero l'oggetto soldatino_1. Cioè stai acquisendo il lock su due oggetti differenti. E non è quindi una "sincronizzazione" corretta tra le due entità.
    Non basta che ci siano banalmente dei metodi synchronized, conta su quale oggetto si sta acquisendo il lock!

    Ecco perché ti consigliavo prima di incapsulare la logica in una classe apposita. Ma per una questione principalmente di "design" che ti permetterebbe però non solo di non "sparpagliare" la logica di attesa tra le due entità ma anche di poter focalizzare l'attenzione sul "unico" lock.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    Java Versions Cheat Sheet

  5. #5
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,305

    Moderazione

    Invito l'autore a prendere visione del Regolamento interno, in particolar modo sull'utilizzo dei titoli delle discussioni.

    In futuro, discussioni con titoli inadeguati, saranno chiuse.


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  6. #6
    Utente di HTML.it
    Registrato dal
    Oct 2002
    Messaggi
    7
    Innanzitutto mi scuso con LeleFT per l'errato titolo, sono super sotto pressione e non avevo ben letto le regole...scusatemi!
    In secondo luogo ringrazio andbin per la pazienza e l'aiuto, come detto in precedenza sono nuovissimo di Java (come é certamente chiaro) e quindi molte domande possono essere stupide.
    Allora ricapitolando, ho capito quello che dici, peró non riesco ancora a capire bene come implementare una ssoluzione.
    Ho provato a lasciare Comandante utilizzante synchronized (quindi su se stesso) e incapsulare in soldatino i methodi che usano myComandante (il riferimento a comandande_1) usando :
    codice:
    synchronized(myComandante){
    ...
    myComandante.isWaitingForAnswer();
    ...
    myComandante.wait();
    ...
    myComandante.getNextQuestion();
    ...
    myComandante.sir();
    purtroppo non sembra funzionare. Anche perche notifyAll() non lo posso sincronizzare con (myComandante) e devo utilizzare synchronized nella signature del metodo che richiama notifyAll().
    Capisco che un'altra configurazione sarebbe piú appropriata, purtroppo lo scheletro di questa cosa mi é stato dato dal Prof e non lo posso cambiare... :-(
    Grazie ancora per l'aiuto!
    Strider
    "Due cose sono infinite: l’universo e la stupidità umana, ma riguardo l’universo ho ancora dei dubbi." A.Einstein

  7. #7
    Utente di HTML.it
    Registrato dal
    Oct 2002
    Messaggi
    7
    Ha funzionato!!!!! grazie a tutti per l'aiuto!!
    per chi volesse spaerlo, ho incluso tutti i metodi in comune all interno di
    synchronized(myComandante){}
    incluso il modificato myComandante.notifyAll()
    e ora funziona (sembra almeno..)
    Ciao alla prossima...(ora inizio l'ultima domanda!)
    Strider
    Strider
    "Due cose sono infinite: l’universo e la stupidità umana, ma riguardo l’universo ho ancora dei dubbi." A.Einstein

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 © 2024 vBulletin Solutions, Inc. All rights reserved.