domenica 19 agosto 2012

Thread...che passione!

Oggi parliamo di questi benedetti Thread e di come si implementano in Java. Per prima cosa vediamo la definizione data da Wikipedia: "un thread o thread di esecuzione è una suddivisione di un processo in due o più filoni, che vengono eseguiti concorrentemente dal processore". In sostanza il thread non è altro che un pezzo di processo. Come si implementa il multi-threading  in Java? ossia come gestire più thread in Java? Esistono due vie, tecnicamente entrambe valide, per implementare il multi-threading e cioè attraverso l'implementazione dell'interfaccia  Runnable o creando una classe che estenda la classe Thread.
Nel primo caso scriviamo una nuova classe che implementi l'interfaccia Runnable e assegniamo un istanza di questa classe ad un nuovo oggetto Thread. Ecco un esempio:

public class SayHello implements Runnable {
private String greeting;

public SayHello(String greeting) {
  this.greeting = greeting;
}

public void run() {
 for(int i = 1; i < = 10; i++) {
 System.out.print(greeting);
 }
 System.out.println(“End of run”);
 }
}

è necessario implementare il metodo run in cui inseriremo il codice che dovrà essere eseguito dal Thread. Tutto questo però non rende un oggetto di classe SayHello un oggetto Thread. Occorre associare l'istanza della classe Say Hello con un nuovo oggetto Thread:

public class CountToTen {
public static void main(String [] args) {
   SayHello hello = new SayHello(“Hi”);
   Thread t = new Thread(hello);
   t.start();
   for(int k = 1; k < = 10; k++) {
       System.out.print(k);
   }
   System.out.println(“End of main”);
  }
}

Nel secondo caso creiamo una nuova classe che estende la classe Thread e in cui sovrascriviamo il metodo run:


public class MyThread extends Thread {
 private String message;
 private boolean keepGoing;

 public MyThread(String m) {
   message = m;
   keepGoing = true;
 }

 public void setKeepGoing(boolean b) {
   keepGoing = b;
 }

 public void run() {
     while(keepGoing) {
         System.out.print(message + “ “);
         try {
                Thread.sleep(1000);
         }catch(InterruptedException e) {}
    }
    System.out.println(“gone!”);
 }
}


Ora non sarà più necessario istanziare due oggetti come avveniva con il precedente pezzo di codice:


public class Main {
 public static void main(String [] args) {
    MyThread myThread = new MyThread(“going”);
    myThread.start();
    try {
           Thread.sleep(6000);
     }catch(InterruptedException e) {}
 myThread.setKeepGoing(false);
 System.out.println(“End of main”);
 } 
}

Ma quale dei due metodi conviene usare? Da un punto di vista object-oriented, l'opzione da preferire per scrivere un thread è implementare Runnable. Infatti cosi facendo si crea una giusta separazione tra l'oggetto thread (che sarà schedulato, sincronizzato ecc.) e l'oggetto runnable che contiene il codice eseguito quando il thread è schedulato.

domenica 8 luglio 2012

Question and answer: pre-intervew

Ma come si svolge un colloquio a Londra presso un azienda informatica? Il processo completo lo spiegherò in dettaglio in un post successivo ma in questo vi fornisco un piccolo suggerimento. L'azienda appena approccia un potenziale candidato, effettua un primo test ponendo diversi quesiti. Questi servono a capire se il candidato ha le basi e se può partecipare ad una interview face to face.Ad esempio per un ruolo come java developer le domande potrebbero essere queste:


1)      What blogs, publications, and websites do regularly you use to keep up to date with the latest technologies? Do you actively contribute to any of them?



2)      In the following example, which features of the Java language are illustrated in (a) methodOne’s parameter list, and (b) the ‘for’ loop?
   class MyNewClass {
       public static void methodOne(String s, String t, Integer ... ii) {
              for(int jj : ii) {
                     System.out.print(jj + " " + s + " " + t);
              }
       }
   }



     3)      Our clients operate in a global market, therefore our applications must operate in many different countries.  Name two basic data types whose format varies between countries, that software must account for.
      4)      Simplify the following section of code.
   public void showCollection (Collection collection) {
         Iterator ii = collection.iterator();
         for(int kk = 0; kk < collection.size(); kk++) {
                 MyClass one = (MyClass) ii.next();
                 one.printResult();
         }
   }


      5)      What feature of the Java programming language is the following code an example of? If you’ve used the feature to solve a problem, please give an example.
   Class c = Class.forName("java.lang.String");
   Method m[] = c.getDeclaredMethods();
     6)      What type of design pattern is this? Can you name one or more potential issues with this pattern?
   public class MyObject {
       private static final MyObject INSTANCE = new MyObject();
private MyObject () {}
public static MyObject getInstance() {
return INSTANCE;
   }
   }


    Sei pronto per questo tipo di domande?

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:

martedì 8 maggio 2012

Sviluppo "guidato": il Test Driven Development

Il test driven development (TDD) è una pratica agile che richiede la creazione di test prima della scrittura del codice sorgente stesso da testare. In realtà è una metodologia utilizzata non per testare il codice, bensì per individuare con precisione le specifiche del software stesso. Ma come avviene questa tipologia di sviluppo? Come mostrato nella figura 1 la prima cosa da fare è quella di creare un test. Il secondo passo consiste nell'eseguire il test. Ovviamente non essendo ancora stato scritto codice per quel test, l'esecuzione del test comporta un fallimento. Occorre quindi apportare delle modifiche al codice in modo che il test sia superato e una volta che ciò avviene si continua con lo sviluppo.

Figura 1. Diagramma sviluppo TDD

Vediamo ora un esempio semplice di codice:


-          Aggiungiamo il test

public void NumberToEnglishShouldReturnOne()
{
  string actual = English.NumberToEnglish(1);
  Assert.AreEqual("one", actual, "Expected the result to be \"one\"");
}

-          Eseguiamo il test. Il test fallisce in quanto il codice non è stato ancora implementato
"NumbersInWords.Test.EnglishTest.NumberToEnglishShouldReturnOne :
    System.Exception :
The method or operation is not implemented.".

-         Scriviamo il codice in modo che il test sia superato
public static string NumberToEnglish(int number)
{
  return "one";
}

-          Eseguiamo di nuovo il test
-          Una volta che il test è passato il prossimo passo è iniziare di nuovo il processo (code refactoring)

Ad esempio il nuovo test sarà:
public void NumberToEnglishShouldReturnTwo()
{
  string actual = English.NumberToEnglish(2);
  Assert.AreEqual("two", actual, "Expected the result to be \"two\"");
}

Quindi modifichiamo il codice in modo che il test sia passato:

public static string NumberToEnglish(int number)
{
  if (number == 1)
    return "one";
  else
    return "two";
}



Ma quali sono i vantaggi di questa metodologia? Il codice. può essere testato singolarmente, sono individuate con precisione le specifiche del codice e sicuramente permette di individuare con facilità lo stato di avanzamento del progetto. Per ulteriori informazioni sul TDD date un'occhiata a questa pagina.

mercoledì 25 aprile 2012

Android e i grafici: GraphView

Mi è capitato l'altro giorno, lavorando a un progetto personale, di dover mostrare dei grafici su alcuni dati memorizzati in un database sqlite. Android non offre nativamente la possibilità di usare i grafici ma esistono diverse librerie Java utilizzabili in Android. Molto interessante ho trovato la libreria GraphView di Jonas Gehring, facile da usare e abbastanza funzionale. Permette la creazione di grafici semplici come line chart e bar chart ma anche qualcosa di complesso come le serie multiple.
Vediamo ora un pezzo di codice che utilizza questa libreria.

Codice Java:


GraphViewData[] data = 
        new GraphViewData[data_from_db.size()];
       double v=0;
       for (int i=0; i<data_from_db.size(); i++) {
data[i] = new GraphViewData(i, data_from_db.get(i));
       }
GraphViewSeries exampleSeries= new GraphViewSeries("Sinus curve", Color.rgb(200, 50, 00), data);
GraphView graphView = new LineGraphView(this, "GraphViewDemo");
graphView.addSeries(exampleSeries); // data
graphView.setScrollable(true);
graphView.setHorizontalLabels(regioni);
graphView.setScalable(true);  
LinearLayout layout = (LinearLayout) findViewById(R.id.graph1);
layout.addView(graphView);
File Xml: 
<?xml version="1.0" encoding="utf-8"?>
<ScrollView android:id="@+id/ScrollView02" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
              xmlns:android="http://schemas.android.com/apk/res/android">
<HorizontalScrollView 
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="2000dip"
android:layout_height="500dip"
android:id="@+id/graph1" />
<TextView  
   android:id="@+id/legend"
   android:layout_width="wrap_content" 
   android:layout_height="wrap_content" 
android:textColor="#ffffff"
android:textSize="17sp" 
    />
  </LinearLayout>
    </HorizontalScrollView>
</ScrollView>

Il codice crea un serie a partire dal vettore data_from_db contenente i dati che vogliamo mostrare nel nostro grafico. Successivamente crea un oggetto di tipo GraphView che rappresenterà il nostro grafico e assegna a tale oggetto la serie creata in precedenza. Infine aggiunge il grafico al LinearLayout definito nel file xml.
Questo è il risultato ottenuto.



Una libreria facile da usare che offre diverse opzioni per rendere più gradevoli ed espliciti i propri grafici su Android. Per maggiori  informazioni consultare il blog ufficiale della libreria.