Problema funzionamento programma riguardante i Thread

di il
3 risposte

Problema funzionamento programma riguardante i Thread

Salve, stavo studiando il linguaggio Java, nello specifico, i Thread. Nel mio libro è riportato un esempio per quanto riguarda il funzionamento di wait() e notify(). Non avendo capito bene il loro funzionamento ho copiato il codice dal libro e mi sono messo a fare il debug passo passo.Il problema è che sul libro mi da come output questo :
Inserito: 1
Ottenuto: 1
Inserito: 2
Ottenuto: 2

ecc ecc. A me, invece non da questo output ma la stringa finale nel main. Se qualcuno cortesemente potesse spiegarmi perchè. allego il codice

package pc;

class Q{
    int n;
    boolean valueSet = false;
    synchronized int get(){
        while(!valueSet){
            try{
            wait();
            }catch(InterruptedException e){
                System.out.println("InterruptedException intercettata");
            }
        }
        System.out.println("Ottenuto: " +n);
        valueSet = false;
        notify();
        return n;
    }


    synchronized void put(int n){
        while(valueSet){
        try{
            wait();
        } catch(InterruptedException e){
                System.out.println("InterruptedException intercettata");
            }
        
        this.n = n;
        valueSet = true;
        System.out.println("Inserito: " +n);
        notify();
        }
   }
}
class Producer implements Runnable{
    Q q;
    Producer(Q q){
        this.q = q;
        new Thread(this, "Producer").start();
    }
    public void run(){
        int i = 0;
        while(true){
            q.put(i++);
        }
    }
}
class Consumer implements Runnable{
    Q q;
    Consumer(Q q){
        this.q = q;
         new Thread(this, "Consumer").start();
    }
    public void run(){
        while(true){
            q.get();
        }
    }
}

public class PC {
    public static void main(String[] args) {
        Q q = new Q();
        new Producer(q);
        new Consumer(q);
        System.out.println("Premere Ctrl+C per fermare");
    }
    
}

3 Risposte

  • Re: Problema funzionamento programma riguardante i Thread

    Rezel97 ha scritto:


    A me, invece non da questo output ma la stringa finale nel main. Se qualcuno cortesemente potesse spiegarmi perchè.
    Innanzitutto la stampa del main la fa comunque e praticamente subito. Il main() è velocissimo, termina quasi istantaneamente. Ma la istanza della JVM NON termina subito, perché ci sono gli altri 2 thread avviati.

    E comunque il problema è un po' subdolo ed è causato dalle { } messe MALE. Nel put() il corpo del while racchiude TUTTO, compreso fino al notify. Questo è sbagliato. Il while deve racchiudere solo il wait (come il get che è corretto).

    A parte questa "svista", la logica di Q è concettualmente e tecnicamente corretta.

    Rezel97 ha scritto:


    riguarda il funzionamento di wait() e notify(). Non avendo capito bene il loro funzionamento
    Se proprio vuoi, te lo posso spiegare. Ma cerca prima sul forum, perché sono quasi sicuro di averlo già spiegato in un modo o nell'altro ...

    Vorrò poi sicuramente spiegarlo sul mio blog ma in queste settimane sono "concentrato" su altri articoli ...
  • Re: Problema funzionamento programma riguardante i Thread

    andbin ha scritto:


    Rezel97 ha scritto:


    A me, invece non da questo output ma la stringa finale nel main. Se qualcuno cortesemente potesse spiegarmi perchè.
    Innanzitutto la stampa del main la fa comunque e praticamente subito. Il main() è velocissimo, termina quasi istantaneamente. Ma la istanza della JVM NON termina subito, perché ci sono gli altri 2 thread avviati.

    E comunque il problema è un po' subdolo ed è causato dalle { } messe MALE. Nel put() il corpo del while racchiude TUTTO, compreso fino al notify. Questo è sbagliato. Il while deve racchiudere solo il wait (come il get che è corretto).

    A parte questa "svista", la logica di Q è concettualmente e tecnicamente corretta.

    Rezel97 ha scritto:


    riguarda il funzionamento di wait() e notify(). Non avendo capito bene il loro funzionamento
    Se proprio vuoi, te lo posso spiegare. Ma cerca prima sul forum, perché sono quasi sicuro di averlo già spiegato in un modo o nell'altro ...

    Vorrò poi sicuramente spiegarlo sul mio blog ma in queste settimane sono "concentrato" su altri articoli ...
    Ti ringrazio infinitamente per aver risolto il problema, avevo il dubbio che fosse un problema relativo ad uno dei cicli while, ma non capivo quale e che tipo di problema. Vedrò di cercare sul forum le spiegazioni a cui accennavi, grazie mille!
  • Re: Problema funzionamento programma riguardante i Thread

    Innanzitutto la stampa del main la fa comunque e praticamente subito. Il main() è velocissimo, termina quasi istantaneamente. Ma la istanza della JVM NON termina subito, perché ci sono gli altri 2 thread avviati.
    Buongiorno, chiedo scusa se ti cito nuovamente dopo aver risolto il problema di ieri, ma non capisco una cosa. Premetto di aver letto sul forum la spiegazione che hai dato riguardo wait() notify() run(), ed ho capito che, bene o male, dopo aver usato start() il metodo run non inizia subito, nel caso specifico ho visto che dopo start() il controllo passa al Thread principale e poi ai vari metodi run(). Quello che non capivo è quali fossero i vari passaggi dentro al codice, quindi ho inserito un paio di println per capire come si muovesse il tutto. Quello che ne è uscito è un output sempre diverso: ho visto che i vari cicli while non sempre vengono fatti partire subito, certe volte dopo 1 o 2 cicli completi di put()/get(), altre volte dopo più di 20 cicli, come mai? Altra cosa, ho visto che, dopo aver completato un metodo synchronized (senza però essere essere entrato nel ciclo while corrispondente e, quindi, senza aver fatto una chiamata a wait() ) il controllo passa comunque al Thread successivo, mi chiedo quindi, se togliessi il notify() e il wait(),o anche solo il wait(), ci sarebbe comunque questa alternanza tra i due Thread? Ti ringrazio e mi scuso per il disturbo. Allego il codice con i vari controlli e un output del codice.
    
    package pc;
    
    class Q{
        int n;
        boolean valueSet = false;
        synchronized int get(){
             System.out.println("punto 1");
            while(!valueSet){
                System.out.println("punto 2");
                try{
                    System.out.println("punto 3");
                wait();
                }catch(InterruptedException e){
                    System.out.println("InterruptedException intercettata");
                }
            }
             System.out.println("punto 4");
            System.out.println("Ottenuto: " +n);
            valueSet = false;
             System.out.println("punto 5");
            notify();
             System.out.println("punto 6");
            return n;
        }
    
    
        synchronized void put(int n){
             System.out.println("punto 7");
            while(valueSet){
                System.out.println("punto 8");
            try{
                 System.out.println("punto 9");
                wait();
            } catch(InterruptedException e){
                    System.out.println("InterruptedException intercettata");
                }
            }
             System.out.println("punto 10");
            this.n = n;
            valueSet = true;
            System.out.println("Inserito: " +n);
             System.out.println("punto 11");
            notify();
             System.out.println("punto 12");
       }
    }
    class Producer implements Runnable{
        Q q;
        Producer(Q q){
            System.out.println("punto 13");
            this.q = q;
            new Thread(this, "Producer").start();
             System.out.println("punto 14");
        }
        public void run(){
             System.out.println("punto 15");
            int i = 0; 
            while(true){
                 System.out.println("punto 16");
                q.put(i++);
                 System.out.println("punto 17");
            }
        }
    }
    class Consumer implements Runnable{
        Q q;
        Consumer(Q q){
            System.out.println("punto 18");
            this.q = q;
             new Thread(this, "Consumer").start();
              System.out.println("punto 19");
        }
        public void run(){
             System.out.println("punto 20");
            while(true){
                 System.out.println("punto 21");
                q.get();
                 System.out.println("punto 22");
            }
        }
    }
    
    public class PC {
        public static void main(String[] args) {
            Q q = new Q();
             System.out.println("punto 23");
            new Producer(q);
             System.out.println("punto 24");
            new Consumer(q);
             System.out.println("punto 25");
            System.out.println("Premere Ctrl+C per fermare");
        }
        
    }
    
    
    OUTPUT:
    punto 23
    punto 13
    punto 14
    punto 24
    punto 15
    punto 18
    punto 16
    punto 7
    punto 10
    punto 19
    punto 25
    Premere Ctrl+C per fermare
    punto 20
    punto 21
    Inserito: 0
    punto 11
    punto 12
    punto 17
    punto 16
    punto 1
    punto 4
    Ottenuto: 0
    punto 5
    punto 6
    punto 7
    punto 10
    punto 22
    punto 21
    Inserito: 1
    punto 11
    punto 12
    punto 17
    punto 16
    punto 1
    punto 4
    Ottenuto: 1
    punto 5
    punto 6
    punto 22
    punto 21
    punto 7
    punto 10
    Inserito: 2
    punto 11
    punto 12
    punto 17
    punto 16
    punto 7
    punto 8 // prima volta che entra dentro al while nel metodo put()
    punto 9
    punto 1
    punto 4
    Ottenuto: 2
    punto 5
    punto 6
    punto 22
    punto 21
    punto 10
    Inserito: 3
Devi accedere o registrarti per scrivere nel forum
3 risposte