Newsgroup: it.comp.java
Titolo: Newby: daemon threads

Salve a tutti!
Sto realizzando una applicazione java per un esame universitario. Ho pensato 
di realizzarla in due parti: una propriamente a livello applicativo, l'altra 
a livello di middleware. Come ho accennato nell'oggetto, sono un 
principiante di Java così ho iniziato a studiare le dispense fornite dai 
professori ed ho capito che il modo migliore di realizzare il middleware è 
tramite un daemon thread...
In pratica vorrei realizzare un servizio che, alla maniera dei programmi TSR 
del vecchio DOS, possa essere avviato o terminato dalla linea di comando. Ad 
esempio eseguendo "java mioservizio" si dovrebbe avviare una istanza del 
servizio nella JVM. Con "java mioservizio /unload" invece si dovrebbe invece 
riuscire a terminare il servizio. Vorrei fare anche in modo che se c'è già 
una istanza di "mioservizio" in esecuzione nella JVM, non ne venga avviata 
una seconda istanza... sostanzialmente mi basterebbe capire come fare a 
verificare se c'è già una istanza in esecuzione in modo da non avviare una 
seconda istanza o da richiamare il metodo che termina il thread.
Sfortunatamente le dispense dei miei professori non mi hanno saputo dare una 
risposta e una ricerca in internet non ha dato frutti (forse perchè non 
sapevo bene cosa cercare: "daemon thread" non ha fornito buoni riscontri). 
Quindi ecco la mia domanda: gentilmente qualcuno di voi potrebbe 
indirizzarmi, o darmi qualche dritta? Sarebbe fantastico se riusciste a 
fornirmi uno straccio di codice che possa studiare e su cui possa fare le 
mie prove!
Grazie in anticipo,
   Stefano 

 seconda istanza o da richiamare il metodo che termina il thread.
quando avvii il demone crei un file di lock,
quando lo chiudi elimini il file.
l'applicazione all'avvio controlli se esiste il file di lock e se esiste si
chiude.
--
Davide Consonni
http://csvtosql.sf.net

 ha scritto nel messaggio 
news:Hq_%d.686436$b5.31...@news3.tin.it...
Ciao Davide!
Grazie per la risposta! Ma che cos'è un file di lock? Un particolare tipo di 
file? Un file che non può essere cancellato?
Nel senso: creando un qualsiasi file, si può verificarne la presenza per 
stabilire se il servizio è in esecuzione o no, ma cause esterne potrebbero 
comunque cancellarlo e creare una potenziale situazione d'errore!
Con questa soluzione, come faccio a recuperare il riferimento al daemon 
thread in esecuzione per dargli lo stop() nel caso volessi chiudere il 
servizio?
Grazie comunque,
     Ste 


Di solito il file di lock è un normale file, solitamente vuoto, creato 
dal programma quando parte in modo da evitare che ce ne sia più di uno 
in esecuzione. Chiaramente se il programma muore senza cancellarlo al 
riavvio non sarebbe più in grado di partire (di solito segnala 
"attenzione ho trovato il file di lock, se c'e' un altro me stesso in 
esecuzione cancellalo").
Per comunicare con un demone in esecuzione potresti usare una porta TCP 
o UDP in modo da inviargli dei comandi. Lui attende sulla porta, un 
altro programma si connette, invia il comando e lui esegue. In unix ci 
sono anche i segnali per comunicare con i processi (kill -qualcosa) ma 
in java credo che la cosa più funzionale sia quello che ho detto prima.
bye
DKano

L'applicazione che devo creare fa largo uso dei sockets... se proprio devo 
ci aggiungo un'altra porta listen... ma se possibile eviterei... c'è già 
abbastanza casino così...
Io avevo in mente qualcosa del tipo dare al thread un certo nome... 
all'avvio della mia applicazione dovrei controllare nel pool dei thread già 
attivi per la presenza di un thread che si chiama col nome che ci ho dato 
io... se c'è e non voglio chiudere il servizio, la mia applicazione termina 
lì... se c'è e voglio chiudere il servizio, dichiaro un thread del mio tipo, 
gli assegno il thread che ho trovato con un type-casting e richiamo il suo 
stop(); se invece non trovo niente, dichiaro il mio thread, lo istanzio, lo 
trasformo in daemon thread e lo avvio...
Solo che del pool dei thread ho solo sentito parlare alla lontana e non so 
come fare... è possibile fare quello che mi prefiggo?
grazie ancora,
   Stefano 

 
Si che si può, ma in locale alla virtual machine... se tu vuoi lanciare 
l'applicazione e chiuderla dall'esterno hai bisogno di un meccanismo di 
comunicazione che esca dalla jvm su cui girano i thread. A meno di 
novità della 1.5 che non conosco, non mi pare ci siano altri metodi se 
non i socket e i file.
bye
DKano
PS il pool dei thread di solito lo usano gli application server (tipo 
bea) come per i pool di connessioni jdbc per evitare le lungaggini della 
creazione; in pratica si tengono sempre in memoria n thread (o 
connessioni o quello che è) e poi se ne assegna a chi lo richiede, 
evitando così di aprirne fisicamente uno ogni volta. Per cercare un 
thread col nome bastano, se non ricordo male, le classi Thread e 
ThreadGroup.
PS2 stop() è deprecato... per interrompere un thread meglio usare un 
flag. Nel thread, a grandi linee:
boolean devoContinuare=true;
....
while(devoContinuare) { //loop principale
...
...
}
public void end() {
  devoContinuare=false;
}

    Ste
In bocca al lupo!
-- 
Fermiamo Scientology prima che sia troppo tardi!!!
http://xenu.com-it.net
 - 
http://xenu.freewinds.cx/
 - 
http://www.xenu.net/
(per rispondere personalmente leva IlDitoDalCulo)

ok, tnx... provo allora ad "immergermi" nella docs di java 1.5...
se non ci salto fuori da solo, disturba se imperverso ancora nel ng 
chiedendo aiuto e magari mostrando il codice?


 ha scritto nel messaggio 
news:4241693c$1...@x-privat.org...

Ci ho passato un pomeriggio senza cavarci un ragno dal buco... Ho cercato 
nella doc di Java ed in Internet, ma forse perchè sono ancora alle prime 
armi (se l'avessi dovuto fare in Delphi, probabilmente in quel pomeriggio 
avrei scritto il grosso del progetto), non sapevo dove cercare o le stringhe 
di ricerca erano pessime... fatto sta che non ho trovato nulla e mi sono 
rivolto al newsgroup...
Se non fossi stato alla frutta non vi avrei disturbati! Ad ogni modo faccio 
un po' di prove... tra gli appunti universitari su Java che ho racimolato 
purtroppo non c'è nulla del genere e non avendo esempi da studiare la cosa è 
ostica...
Ma chi l'ha dura la vince!
Grazie per l'incoraggiamneto,
    Ste 

>> un meccanismo di comunicazione che esca dalla jvm su cui girano i thread.
Questo meccanismo di comunicazione è già stato implementato da altri ed è
attualmente in uso in diversi prodotti:
http://wrapper.tanukisoftware.org/doc/english/introduction.html
Java Service Wrapper presenta alla tua applicazione (o servizio che dir si
voglia) un'interfaccia comune per:
1) ricevere/inviare le notifiche di avvio,pausa e arresto
2) poter eseguire un logging uniforme utilizzando i servizi nativi del
sistema operativo (syslog/event viewer)
c'è parecchia documentazione da leggere...
Buon lavoro!!!


Grazie per le dritte... ci do un'occhiata subito! Chiedo scusa se ieri non 
ho risposto subito, ma stavo guardando anche un po' di UML per impararlo e 
approfondirlo... (devo fare anche un po' di documentazione per il lavoretto 
che sto facendo)...
Ad ogni modo, ieri notte ho prodotto questo codice:
class PrimeThread extends Thread {
 PrimeThread(String str) {
  super (str);
 }
 public void run() {
  for (int i = 0; i < 10; i++) {
   // Display some information about us...
   System.out.println (i + ") Hello from " + getName() + "!");
   System.out.println (this.isDaemon () ? "I'm a daemon!" : "I'm a 
thread...");
   System.out.println ("I'm part of '" + this.getThreadGroup () + "' thread 
group.");
   System.out.println ("There are other " + this.activeCount () + " active 
threads in this group:");
   // Get list of threads in our same group and enumerate them...
   Thread[] threadList = new Thread[this.activeCount ()];
   this.enumerate (threadList);
   for (int l = 0; l < threadList.length; l++) {
    System.out.println ("- " + threadList[l].getName ());
   }
   System.out.println 
("------------------------------------------------------------");
   // Wait some time before repeating the same...
   try {
    sleep ((int)Math.random() * 3000);
   } catch (InterruptedException e) {
    System.err.println (getName() + "can't wait...");
   }
  }
  System.out.println 
("============================================================");
 }
}
public class Prototype002 {
    public static void main(String[] args) {
        // Display Prototype Name.
        System.out.println ("Prototype 002\n");
        // Create a new thread (defaults to "main")
  PrimeThread p = new PrimeThread ("Pippo");
  p.setDaemon (true);
  p.start ();
        // Hook to "main" thread group
        ThreadGroup MainGroup = new ThreadGroup ("main");
        // Display "main" thread group info
        System.out.println ("Main active threads: " + MainGroup.activeCount 
());
        MainGroup.list ();
        System.out.println ("");
        // Display each tread name in "main" group
        for (int i = 0; i < MainGroup.activeCount (); i++)
         System.out.println (""); // not yet completed
    }
}
Ci sono tuttavia alcune cose che non mi spiego... Intanto riporto l'output 
che il suddetto codice produce a runtime:
Prototype 002
Main active threads: 0
java.lang.ThreadGroup[name=main,maxpri=10]
0) Hello from Pippo!
I'm a daemon!
I'm part of 'java.lang.ThreadGroup[name=main,maxpri=10]' thread group.
There are other 2 active threads in this group:
- Pippo
- DestroyJavaVM
------------------------------------------------------------
1) Hello from Pippo!
I'm a daemon!
I'm part of 'java.lang.ThreadGroup[name=main,maxpri=10]' thread group.
There are other 2 active threads in this group:
- Pippo
- DestroyJavaVM
------------------------------------------------------------
2) Hello from Pippo!
I'm a daemon!
I'm part of 'java.lang.ThreadGroup[name=main,maxpri=10]' thread group.
There are other 2 active threads in this group:
- Pippo
- DestroyJavaVM
------------------------------------------------------------
3) Hello from Pippo!
I'm a daemon!
I'm part of 'java.lang.ThreadGroup[name=main,maxpri=10]' thread group.
There are other 2 active threads in this group:
- Pippo
- DestroyJavaVM
------------------------------------------------------------
4) Hello from Pippo!
I'm a daemon!
I'm part of 'java.lang.ThreadGroup[name=main,maxpri=10]' thread group.
There are other 2 active threads in this group:
- Pippo
- DestroyJavaVM
------------------------------------------------------------
5) Hello from Pippo!
I'm a daemon!
I'm part of 'java.lang.ThreadGroup[name=main,maxpri=10]' thread group.
There are other 2 active threads in this group:
- Pippo
- DestroyJavaVM
------------------------------------------------------------
6) Hello from Pippo!
I'm a daemon!
I'm part of 'java.lang.ThreadGroup[name=main,maxpri=10]' thread group.
There are other 2 active threads in this group:
- Pippo
- DestroyJavaVM
------------------------------------------------------------
7) Hello from Pippo!
I'm a daemon!
I'm part of 'java.lang.ThreadGroup[name=main,maxpri=10]' thread group.
There are other 2 active threads in this group:
- Pippo
- DestroyJavaVM
------------------------------------------------------------
8) Hello from Pippo!
I'm a daemon!
I'm part of 'java.lang.ThreadGroup[name=main,maxpri=10]' thread group.
There are other 2 active threads in this group:
- Pippo
- DestroyJavaVM
------------------------------------------------------------
9) Hello from Pippo!
I'm a daemon!
I'm part of 'java.lang.ThreadGroup[name=main,maxpri=10]' thread group.
There are other 2 active threads in this group:
- Pippo
- DestroyJavaVM
------------------------------------------------------------
============================================================
Process completed.
Innanzitutto noto che la JVM fa prima terminare la mia applicazione e poi fa 
partire il mio daemon: la mia applicazione non è altro che un thread 
all'interno della JVM, quindi sapendo che implementa uno scheduling 
semplicemente preemptive e che non ho pasticciato sulle priorità dei thread, 
la cosa non mi stupisce più di tanto e la trovo accettabile...
Stando alle informazioni che sono riuscito a recuperare su Thread e 
ThreadGroup, se all'atto della creazione di un Thread non lo assegno ad 
alcun ThreadGroup in particolare, la JVM lo assegna d'ufficio ad un gruppo 
di default chiamato "main". Facendo affidamento su questa informazione ho 
provato a creare una istanza di un ThreadGroup chiamandola "main", proprio 
come il gruppo di default... Speravo in questo modo di agganciare lo stesso 
gruppo agganciato in altro modo all'interno del Thread che mostra 
correttamente Pippo e DestroyJavaVM come membri per poterci interagire, ma 
evidentemente ho invece creato un sotto gruppo di nome "main" all'interno 
del gruppo di default "main" e che quindi viene correttamente mostarto come 
vuoto...
Dopo questo lunghissimo parto, ecco la domanda: come faccio invece ad 
"attaccarmi" al vero "main"? Non credo che sia necessario qualcosa più lungo 
di un paio di righe... ma proprio non sono risucito a trovarle da solo... 
please help me!
Ciao,
   Ste 

probabilmente ci si riesce con clone()... ma non so cosa copiare...
Ste 

Altra aggiunta...
Ho modificato il main in questo modo:
public class Prototype002 {
    public static void main(String[] args) {
        // Display Prototype Name.
        System.out.println ("Prototype 002\n");
        // Create a new thread (defaults to "main")
  PrimeThread p = new PrimeThread ("Pippo");
  System.out.println ("\nThread instanzianto");
  Thread[] threadList1 = new Thread[p.activeCount ()];
  p.enumerate (threadList1);
  for (int l = 0; l < threadList1.length; l++) {
   System.out.println ("- " + threadList1[l].getName ());
  }
  p.setDaemon (true);
  System.out.println ("\nThread instanzianto e demonizzato");
  Thread[] threadList2 = new Thread[p.activeCount ()];
  p.enumerate (threadList2);
  for (int l = 0; l < threadList2.length; l++) {
   System.out.println ("- " + threadList2[l].getName ());
  }
  p.start ();
  System.out.println ("\nThread instanzianto, demonizzato e avviato");
  Thread[] threadList3 = new Thread[p.activeCount ()];
  p.enumerate (threadList3);
  for (int l = 0; l < threadList3.length; l++) {
   System.out.println ("- " + threadList3[l].getName ());
  }
  // Hook to "main" thread group
        ThreadGroup MainGroup = new ThreadGroup ("main");
        // Display "main" thread group info
        System.out.println ("Active groups: " + MainGroup.activeGroupCount 
());
        System.out.println ("Main active threads: " + MainGroup.activeCount 
());
        MainGroup.list ();
        System.out.println ("");
        // Display each tread name in "main" group
        for (int i = 0; i < MainGroup.activeCount (); i++)
         System.out.println (""); // not yet completed
    }
}
e ho notato che ottengo delle risposte positive: vedo"main" che prima non 
c'era perchč il mio thread partiva quando ormai il programma era terminato, 
ma non vedo piů "DestroyJavaVM"... com'č sto fatto????
Ste 

Se ho ben capito il tuo 'demone' utilizza delle porte TCP/IP su cui si
mette in ascolto. Quindi quando lo attivi si mette in ascolto per
esempio la porta 9999. Bene a questo punto se tu cerchi di lanciare lo
stesso programma, questo cercherà di mettersi in ascolto anche lui
sulla porta 9999, ma trovandola già occupata ti manderà una bella
eccezione... e auindi non parte. A te non resta che il piacere di
intercettare l'eccezione, mandare all'utente un bel messaggino e
chiudere il programma. E il tuo problema di non lanciare il servizio
due volte è belle che risolto...
Per quanto riguarda lo spegnimento non esiste tecnica diversa da
quella di mandargli un segnale su una porta TCP/IP... guardacaso è la
strada che seguono tutti gli application server a partire da Tomcat.
Quindi rassegnati, o apri una porta in ascolto per il segnale di
chiusura, oppure usi una porta già aperta e ti aspetti su questa un
segnale precodificato.
Bye