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.