Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
Java - problema multithreading e campi statici
Forum - Java - problema multithreading e campi statici

Avatar
robyp7 (Normal User)
Newbie


Messaggi: 13
Iscritto: 02/07/2008

Segnala al moderatore
Postato alle 9:30
Sabato, 05/07/2008
Ciao!

scusate ho un programma che utilizzando il multithreading genera dei numeri primi. Praticamente voglio che il primo thread generi poi quando il controllo passa al secondo thread, questo continui a generare partendo dall'ultimo valore a cui era arrivato il thread precendente. Il problema è che ho usato una variabile p statica per condividere nei thread l'ultimo valore generato e un sync(nomeclasse.class) per avere la mutua esclusione su tale variabile statica in modo che due thread non eseguano contemporaneamente la procedura di generazione numeri primi con il risultato negativo di dare lo stesso valore. La cosa però non sempre funziona perchè a volte quando il controllo da un thread passa a l'altro, l'altro riparte dal valore precedente e rigenera per cui l'ultimo valore del precedente thread a cui è stato tolto il controllo. Per fare un es: thread-1 genera 2-3-5 poi il controllo passa al thread-2 che rigenera ancora 5 e poi continua bene a generare 7-9 ecc..

A questo punto o ho sbagliato qualcosa o con i multithread meglio lasciare perdere i campi statici e cambiare radicalmente il prog, ma dato che al momento sono carente di idee qalcuno mi può dare un consiglio? grazie

allego il programma:


import java.awt.List;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.ListIterator;

import sun.text.CompactShortArray.Iterator;


public class CancelThdEx<T> implements Runnable {
        
private static final ArrayList<BigInteger> primes
        = new ArrayList<BigInteger>();
private volatile boolean  
                 cancelled  = false;
private static BigInteger p = BigInteger.ONE;
            
public CancelThdEx(){
    new Thread(this).start();
}

public void run() {
//BigInteger p = BigInteger.ONE;
     while (!cancelled ) {
        synchronized (CancelThdEx.class) {
     p = p.nextProbablePrime();
        }
       synchronized (this) {
            System.out.println
         (Thread.currentThread().getName()  
          + " : " + p.toString());
    primes.add(p);

         }
      }//end while
}
        
    
public static void printResults(){
    ListIterator<BigInteger> i = (get()).listIterator();
while (i.hasNext()){

System.out.println(Thread.currentThread().getName() + " : ");
                 System.out.println((i.next()));
             }
             System.out.println("Size of List: " + (get().size()));
}

public void cancel() { cancelled = true;  }

public static ArrayList<BigInteger> get() {
   return new ArrayList<BigInteger>(primes);
  }
        
public static void main(String []args) throws Exception{
    CancelThdEx c = new CancelThdEx();
     CancelThdEx c2 = new CancelThdEx();
    Thread.currentThread().sleep(300);
     c.cancel();
     c2.cancel();
      printResults();
    }
}


robyp7 ha allegato un file: CancelThdEx.zip (909 bytes)
Clicca qui per scaricare il file
PM Quote
Avatar
VaLeRiO (Ex-Member)
Pro


Messaggi: 114
Iscritto: 28/06/2008

Segnala al moderatore
Postato alle 11:51
Sabato, 05/07/2008
Ho dato un'occhiata superficiale comunque ti consiglierei di usare non un'arrayList ma un
ArrayBlockingQueue. Io l'ho usato per la sincronizzazione con i metodi "put()" e "take()" ma dovresti riuscire anche tu in qualche modo a usufruirne.

Così hai la certezza della mutua esclusione.

Comunque non ho capito perchè usare il multithreading se comunque ogni thread riprende da quello precedente :-|

Al massimo dai dei range ovvero thread1 cerca da 1 a 10000, thread2 da 10000 a 20000 e i controlli li effettui su questi numeri.

Sai che comunque implementare una sorta di tuo ascoltatore non sarebbe male così non devi badare a tutte questo.

Guardati il vPortScanner che ho uploadato.
Guarda come funziona l'ascoltatore e come invio al ricevente le porte aperte trovate. Tu puoi fare in modo analogo.

Ultima modifica effettuata da VaLeRiO il 05/07/2008 alle 11:53
PM Quote
Avatar
robyp7 (Normal User)
Newbie


Messaggi: 13
Iscritto: 02/07/2008

Segnala al moderatore
Postato alle 19:00
Domenica, 06/07/2008
OK seguirò come dici..
volevo chiederti su un dubbio, tu che sai..se io ho una classe che è un thread mettiamo si chiami pippo

e nel main faccio

new Thread(new Pippo()).start
new Thread(new Pippo()).start

mi crea due thread così, è  possibile? ma li tratta come trhead diversi che agisocno sulla stessa istanza cioè Pippo (scrivono sulle stesse variabili quindi) o no? sono due thread concorrenti ed occorre usare la sincronizzazione se si va a modificare ad esempio una variabile della classe pippo?? Nel mio caso forse avrei dovuto fare una classe e passare la stessa istanza di tale calsse ai costruttori dei due thread che mi ero creato così evito di usare campi statici e usando la sincronizzazione..meglio no?


Testo quotato

Postato originariamente da VaLeRiO:

Ho dato un'occhiata superficiale comunque ti consiglierei di usare non un'arrayList ma un
ArrayBlockingQueue. Io l'ho usato per la sincronizzazione con i metodi "put()" e "take()" ma dovresti riuscire anche tu in qualche modo a usufruirne.

Così hai la certezza della mutua esclusione.

Comunque non ho capito perchè usare il multithreading se comunque ogni thread riprende da quello precedente :-|

Al massimo dai dei range ovvero thread1 cerca da 1 a 10000, thread2 da 10000 a 20000 e i controlli li effettui su questi numeri.

Sai che comunque implementare una sorta di tuo ascoltatore non sarebbe male così non devi badare a tutte questo.

Guardati il vPortScanner che ho uploadato.
Guarda come funziona l'ascoltatore e come invio al ricevente le porte aperte trovate. Tu puoi fare in modo analogo.


PM Quote
Avatar
robyp7 (Normal User)
Newbie


Messaggi: 13
Iscritto: 02/07/2008

Segnala al moderatore
Postato alle 19:10
Domenica, 06/07/2008
Scusa! ho sbagliato a scrivere!

volevo in realtà scrivere

Pippo c = new Pippo();//Pippo implementa Runnable
new Thread(c).start
new Thread(c).start

Testo quotato

Postato originariamente da robyp7:

OK seguirò come dici..
volevo chiederti su un dubbio, tu che sai..se io ho una classe che è un thread mettiamo si chiami pippo

e nel main faccio

new Thread(new Pippo()).start
new Thread(new Pippo()).start

mi crea due thread così, è  possibile? ma li tratta come trhead diversi che agisocno sulla stessa istanza cioè Pippo (scrivono sulle stesse variabili quindi) o no? sono due thread concorrenti ed occorre usare la sincronizzazione se si va a modificare ad esempio una variabile della classe pippo?? Nel mio caso forse avrei dovuto fare una classe e passare la stessa istanza di tale calsse ai costruttori dei due thread che mi ero creato così evito di usare campi statici e usando la sincronizzazione..meglio no?


Testo quotato

Postato originariamente da VaLeRiO:

Ho dato un'occhiata superficiale comunque ti consiglierei di usare non un'arrayList ma un
ArrayBlockingQueue. Io l'ho usato per la sincronizzazione con i metodi "put()" e "take()" ma dovresti riuscire anche tu in qualche modo a usufruirne.

Così hai la certezza della mutua esclusione.

Comunque non ho capito perchè usare il multithreading se comunque ogni thread riprende da quello precedente :-|

Al massimo dai dei range ovvero thread1 cerca da 1 a 10000, thread2 da 10000 a 20000 e i controlli li effettui su questi numeri.

Sai che comunque implementare una sorta di tuo ascoltatore non sarebbe male così non devi badare a tutte questo.

Guardati il vPortScanner che ho uploadato.
Guarda come funziona l'ascoltatore e come invio al ricevente le porte aperte trovate. Tu puoi fare in modo analogo.



PM Quote
Avatar
VaLeRiO (Ex-Member)
Pro


Messaggi: 114
Iscritto: 28/06/2008

Segnala al moderatore
Postato alle 19:42
Domenica, 06/07/2008
Pippo dovrebbe implementare Runnable per essere passato a parametro al Thread e fatto partire come Thread.

Quando fai thread.start() richiami il metodo di Pippo run(). Se l'istanza è la stessa lo richiami due volte.

Le variabili che modifichi sono le stesse, però sinceramente non so come si comporti in questi casi .. quindi l'unico modo è provarlo.

Teoricamente funziona come sopra, praticamente dovresti appunto provare.

Ciao :P

Ultima modifica effettuata da VaLeRiO il 06/07/2008 alle 19:53
PM Quote
Avatar
robyp7 (Normal User)
Newbie


Messaggi: 13
Iscritto: 02/07/2008

Segnala al moderatore
Postato alle 20:47
Mercoledì, 09/07/2008
Guarda ho fatto delle prove
In effetti come logica l'istanza è la stessa la classe thread è in se un wrapper per un oggetto runnable, il quale come dici tu invoca il suo metodo run quindi se l'istanza è la stessa anche le variabili in teoria sono le stesse e come provato togliendo static ho lo stesso effetto di avere due istanze distinte con i campi statici.
Però il nome dei due thread con l'istanza uguale è diverso ma quello credo che fa poco testo(logicamente ad ogni invocazione di una nuova istanza di thread qualche suo metodo cambia il nome). Guarderò il codice.

Grazie!
Ciao

Testo quotato

Postato originariamente da VaLeRiO:

Pippo dovrebbe implementare Runnable per essere passato a parametro al Thread e fatto partire come Thread.

Quando fai thread.start() richiami il metodo di Pippo run(). Se l'istanza è la stessa lo richiami due volte.

Le variabili che modifichi sono le stesse, però sinceramente non so come si comporti in questi casi .. quindi l'unico modo è provarlo.

Teoricamente funziona come sopra, praticamente dovresti appunto provare.

Ciao :P


PM Quote
Avatar
logos (Normal User)
Newbie


Messaggi: 1
Iscritto: 30/05/2009

Segnala al moderatore
Postato alle 14:15
Sabato, 30/05/2009
ad un certo punto nel tuo codice tu scrivi questa cosa:
Thread.currentThread().sleep(300);

Questa è una cosa molto fuorviante.
ti spiego brevemente il perchè...
il metodo sleep è un metodo STATICO della classe Thread, quindi va chiamato così
Thread.sleep(300);
la cosa fuorviante è quel currentThread() (ke restituisce il riferimento al thread corrente), sembra quasi, scritto in quella maniera, che sia possibile chiamare il metodo sleep anke su un thread diverso da quello corrente... mentre il metodo sleep agisce già e SOLO sul thread corrente.

una precisazione ke andava fatta...
alla prossima.

PM Quote