sabato 30 giugno 2012

Volatile: cosa vuol dire in Java?

Spesso accade durante una interview che venga chiesto cosa sia e cosa voglia dire la keyword "volatile" in Java. Questa parola è usata per indicare ad un Thread di non memorizzare il valore di una variabile nella cache ma direttamente nella memoria principale. Perché? Ora immaginiamo che il Thread A modifichi il valore della variabile "pippo". Se il Thread B deve leggere il valore di tale variabile potrebbe accadere che il suo valore non sia stato ancora aggiornato con le modifiche di A. Con la parola chiave volatile si forza il Thread A a rendere visibili gli aggiornamenti fatti immediatamente.
Ora proviamo a vedere un esempio.


public class Singleton{private static volatile Singleton _instance;
public static Singleton getInstance(){
   if(_instance == null){
            synchronized(Singleton.class){              

              if(_instance == null)
                  _instance = new Singleton();
            }
   }
   return _instance;
}



Se non rendiamo la variabile _instance volatile allora il Thread che sta creando l'istanza di "SIngleton", non è in grado di comunicare a gli altri Thread che l'istanza è stata creata fino a che non finirà l'esecuzione del blocco singleton; quindi se il A sta creando un istanza di Singleton e appena dopo la creazione perde la CPU allora tutti gli altri Thread non saranno in grado di vedere il valore della variabile _instance come non nullo e crederanno che il suo valore sia ancora null.
Infine da ricordare che la parola chiave volatile è valida solo per le variabili. Questa differenzia la parola chiave volatile dalla parola chiave synchronized. 

venerdì 15 giugno 2012

Java ecologico: le variabili d'ambiente e il CLASSPATH


Quando si parla di compilazione di codice Java sicuramente vi sarà capitato di sentir parlare di variabili d'ambiente e CLASSPATH. Il classpath si riferisce al percorso sul tuo file system dove i tuo file .class sono salvati. Il classpath è definito dalla variabile d'ambiente CLASSPATH. Il CLASSPATH specifica le directory e i file JAR dove il compilatore e la JVM troveranno il bytecode. Attraverso l'utilizzo del CLASSPATH si permette di memorizzare il bytecode in directory a nostra scelta o in archivi Java (JAR File).

Rendi ecologico il tuo pc con le variabili d'ambiente..


Per esempio supponiamo di avere la classe com.bustapaga.Impiegato. Il compilatore e la JVM cercheranno la directory \com\bustapaga basandosi sulla variabile d'ambiente CLASSPATH. Quindi se per esempio il file Impiegato.class si trova nella directory

c:\Documents and Settings\Alex\workspaces\build\com\bustapaga

allora la variabile CLASSPATH deve includere la directory

c:\Documents and Settings\Alex\workspaces\build

La variabile CLASSPATH può contenere un qualsiasi numero di directory e file JAR.

Ma come settare questa variabile d'ambiente? Dipende ovviamente dal sistema operativo.

Sotto un sistema Windows: aprire il prompt dei comandi e settare la variabile classpath con questa istruzione (separando i multi valori con il punto e virgola)

set CLASSPATH=”c:\Documents and Settings\Alex\workspaces\build”;
c:\myproject\build;c:\tomcat\lib\servlet.jar;.;

Sotto un sitema Unix: usare il comando setenv per separare valori multipli

setenv CLASSPATH /usr/build:/myproject/build:/tomcat/lib/servlet.jar

Attenzione! Un errore comune da evitare è quello di includere parte del nome del percorso del package nella variabile CLASSPATH. Da evitare ad esempio un errore simile:

set CLASSPATH=c:\myproject\build\com\bustapaga;

mercoledì 13 giugno 2012

Che tipi! Primitive Types vs. Reference Types


Le applicazioni Java prevedono due tipi di dati: primitivi e referenziati. I tipi primitivi sono i classici tipi di dati che si imparano sin dalle prime lezioni di programmazione e sono riassunti nella tabella qui sotto.



La tabella mostra anche i diversi range di valori permessi per ogni tipo. Difficile ricordare ogni singolo range mentre può essere molto utile ricordare la dimensione in bits prevista per ogni tipo.

Un Reference type invece, sono variabili che sono tipi di classe, tipi di interfacce o tipi di array. Una "reference" fa riferimento a un oggeto (un istanza di una classe). A differenza dei tipi primitivi che mantengono i loro valori im memoria dove la variabile è allocata, le referenze non mantengono il valore dell'oggetto a cui si riferiscono. Una referenza "punta" ad un oggetto memorizzando l'indirizzo dove l'oggetto è collocato. Tutto questo può essere ricondotto al conetto di "puntatore". Tuttavia Java non permette al programmatore di accedere direttamente ad un indirizzo fisico di memoria. Quindi anche se le referenze sono simili ai puntatori, è possibile solo usare una referenza per accedere ad un campo o un metodo dell'oggetto a cui fa riferimento. Risulta impossibile quindi determinare il reale indirizzo di memoria della variabile referenziata.
Vediamo un esempio ora. Dichiariamo due referenze:

java.util.Date today;
String greeting;

La variabile today è una refernza di tipo Date e può puntare solo a un oggetto di tipo Date. La variabile greeting invece è una referenza che può puntare solo ad un oggetto di tipo String. Un valore può essere assegnato ad una referenza in due modi:
- Una referenza può essere assegnata ad una referenza dello stesso tipo
- Una referenza può essere assegnata ad un nuovo oggetto usando la parola chiave "new"

Ad esempio assegnamo le due precedenti referenze a due nuovi oggetti:

today = new java.util.Date();
greeting = “How are you?”;

Ecco come queste due referenze sono rappresentate in memoria: