Visualizzazione post con etichetta Thread. Mostra tutti i post
Visualizzazione post con etichetta Thread. Mostra tutti i post

02 novembre 2008

java.lang.IllegalThreadStateException problema restart di un thread java

In alcuni casi è necessario dover gestire un numero di thread paralleli considerevole.
Si noti che in queste situazioni si presenta un deterioramento delle prestazioni dovuto principalmente al costo computazione di creazione e distruzione dei thread.
In questi casi è opportuno sviluppare una strategia tale da riuscire a riutilizzare i thread senza crearne altri. Il problema è che in Java, dopo aver creato un thread non è possibile riavviare la propria esecuzione mediante il metodo start().

Ecco un esempio di come creare un thread, escogitando un metodo per poterne gestire il "re"start.
public class MyThread extends Thread{ 
public Integer semaforoThread = new Integer(0);
// metodo run
public void run(){
try{
while(true){
// codice da far eseguire al thread
....

synchronized(semaforoThread){
semaforoThread.wait();
}
}
}catch(InterruptedException e){
System.out.println("Problemi con il thread : "+e.getMessage());
}
}
// metodo per far ripartire il thread
public void restart(){
synchronized (this.semaforoThread) {
this.semaforoThread.notify();
}
}
}

Questo è il codice per poter utilizzare tale thread :
MyThread thread = new MyThread();
thread.start();
....
// si intende restartare il thread
thread.restart();

28 settembre 2008

Thread Concorrenti in Java

In alcuni casi, quando ci si trova nella situazione in cui vengono eseguiti diversi task in sequenza, ciascuno dei quali è indipendente dagli altri, e si ha la necessità di dover ridurre i tempi di elaborazione, strutturare il coidice in maniera tale da eseguire thread paralleli può essere una soluzione.
Nel mio esempio si ha la necessità di eseguire 3 chiamate a WebServices, che come ben sapete sono chiamate sincrone (bloccano il processo chiamante fino ad una risposta o un failure), quindi il tempo totale di esecuzione è dato da :
n_task
∑ ExecTime(i)
i=0


Introducendo una strategia di gestione mediante thread paralleli si può ridurre il tempo di esecuzione al :
n_task
Max(ExecTime(i))
i=0


Supponiamo di modificare il codice di una classe ClassSample inserendo tra le proprietà le seguenti 3 dichiarazioni:
public Integer cont = new Integer(0);
public Integer sincronizzatore = new Integer(0);
public static final int NUM_THREAD = 3;


La variabile cont rappresenta il contatore dei thread che hanno già terminato la propria esecuzione.
La variabile sincronizzatore rappresenta l'oggetto che funge da sincronizzatore.
La variabile statica NUM_THREAD che rappresenta il numero di thread che verranno eseguiti (tale numero è statico ma può dipendere dal contesto)

A questo punto è necessario definire i Thread, nel mio esempio assumiamo che i thread siano delle chiamate a servizi Web che come ben sapete sono chiamate bloccanti :
class Servizio1Thread extends Thread { 
/***
* Metodo run per avviare il thread
*/
public void run() {
// Parte thread Ws
RisultatoServizio risultatoServizio = chiamoServizio(parametro1,parametro2);
controllaSemaforo();

}
}


Definiamo la funzione che controlla l'esecuzione di tutti i Threads
>/***
* Metodo controllore dei thread completati. Nel caso in cui
* siano stati completati tutti i thread invoca una notifica al thread
* principale che è temporaneamente in stato di wait
*/
public void controllaSemaforo (){
synchronized (sincronizzatore){
logger.debug("processi chiusi "+(cont.intValue()+1)+"/"+NUM_THREAD);
if (cont.intValue()+1<NUM_THREAD){
cont = new Integer(cont.intValue()+1);
}else{
logger.debug("notifico al thread principale");
sincronizzatore.notifyAll();
}
}
}


Ora passiamo all'implementazione del Thread principale, che si occuperà di lanciare i 3 Thread paralleli e attenderne il completamento prima di continuare con il normale flusso di esecuzione.
//Thread 1 
Servizio1Thread myFirstThread = new Servizio1Thread ();
myFirstThread.start();
//Thread 2
Servizio2Thread myRirThread = new Servizio1Thread ();
myRirThread.start();
//Thread 3
Servizio3Thread myWsThread = new Servizio1Thread ();
myWsThread.start();

try{

// blocco sincronizzato per attendere i risultati
synchronized(sincronizzatore) {
//Fermo il thread principale
sincronizzatore.wait();
// Hanno finito i thread che hanno sbloccato l'esecuzione del Thread principale
}
// qui continua il normale flusso di esecuzione
}catch(InterruptedException ex){
System.out.println("Eccezione : "+ex.getMessage());
}

Naturalmente si può giocare con le chiamate in maniera opportuna all'operazione che si intende eseguire. Spero che tale soluzione velocizzerà le vostre applicazioni. Alla prossima!