View Full Version : [URGENTE-JAVA 1.5]Programmazione multithreading
ShadowX84
17-07-2007, 15:13
Salve,
so, non per esperizenza diretta, che fino a Java 1.4, la più piccola "unità" era il thread.
Avrei la necessità di sapere se da Java 1.5 in poi è stata introdotta "un'entità" più piccola del thread.
Provo a spiegarmi meglio: è possibile suddividere un thread?
Grazie in anticipo a tutti.
Avrei la necessità di sapere se da Java 1.5 in poi è stata introdotta "un'entità" più piccola del thread.
Provo a spiegarmi meglio: è possibile suddividere un thread?No.
Quale è la tua necessità?
A naso direi di no ma bisognerebbe vedere qui cosa si intende per "unità". Se intendiamo unità nel senso di flusso di esecuzione allora il Thread è effettivamente unitario.
Tuttavia il Thread non è un monolite. Alla lontana, è una pila di "frame" dove ogni frame è la rappresentazione dei dati necessari all'esecuzione di un metodo. Man mano che si svolte, il flusso di esecuzione rappresentato dal Thread accumula e decumula questi frame, creati ogni volta che intervenga l'invocazione di un metodo.
Sono in ogni caso ragionamento validi dalla notte dei tempi. Ciò che è cambiato nella storia della piattaforma Java dal punto di vista della concorrenza è stato una definizione più stringente delle norme relative al modello di memoria e, in Java 5, l'introduzione di strumenti di controllo più astratti rispetto alle istruzioni di gestione della concorrenza integrati nel linguaggio. Prima c'era solo "volatile boolean x" oggi c'è anche "java.util.concurrent.atomic.AtomicBoolean x;", giusto per dirne una.
ShadowX84
17-07-2007, 15:35
Grazie ad entrambi, sono io che sono un cane... provo a spiegarmi meglio, con un esempio concreto.
(Però non mi chiedete come siamo arrivati a questo livello...che sono in quest'azienda da troppo poco tempo).
Allora, utilizziamo un gestionale sviluppato apposta per la nostra azienda.
Gestionale che è stato spostato sul nuovo server, che è un dual socket equipaggiato con due xeon quad core e 16 GB di Ram.
Ci siamo accorti che il gestionale non è stato sviluppato per sfruttare sistemi multi core (o multi cpu...fate vobis), e di conseguenza abbiamo 1core al 100% e sette core che stanno a grattarsi e ovviamente quando il gestionale è chiamato a fare un lavoro pesante...blocca o per lo meno rallenta (ovviamente) tutti i client che hanno un'istanza del gestionale aperta.
Siccome per il momento è impensabile mettersi a rendere il lato server multithreading, (oltre ad essere un lavoro enorme..a quel punto converrebbe riscriverlo da zero), volevo sapere se c'era modo di poter "spezzare" il thread evitando così che utilizzi soltanto una CPU.
Scusate ancora, ma la fretta non aiuta ad essere molto esplicativi...
sul nuovo server, che è un dual socket equipaggiato con due xeon quad core e 16 GB di Ram.Il sistema che ho sempre sognato di avere ma che non posso permettermi .... :fagiano:
Ci siamo accorti che il gestionale non è stato sviluppato per sfruttare sistemi multi core (o multi cpu...fate vobis), e di conseguenza abbiamo 1core al 100% e sette core che stanno a grattarsi e ovviamente quando il gestionale è chiamato a fare un lavoro pesante...blocca o per lo meno rallenta (ovviamente) tutti i client che hanno un'istanza del gestionale aperta.
Siccome per il momento è impensabile mettersi a rendere il lato server multithreading, (oltre ad essere un lavoro enorme..a quel punto converrebbe riscriverlo da zero), volevo sapere se c'era modo di poter "spezzare" il thread evitando così che utilizzi soltanto una CPU.Il parallelismo, cioè il poter eseguire più operazioni "contemporaneamente", non è una cosa che si può attivare così su due piedi su del codice già scritto. Va pianificato, studiato e verificato attentamente quando si progetta l'applicazione.
Ci sono questioni per nulla banali che riguardano la sincronizzazione tra thread, accesso a risorse condivise, ecc....
E qui mi sorge una curiosità latente e mai soddisfatta.
Se un programma è multiprocesso (più JVM per la stessa applicazione) nulla questio: è possibile assegnare almeno una JVM per ogni core e via.
Ma se il programma è multithreading (una sola JVM) i diversi Thread possono essere gestiti da diversi core?
Comunque sia, una cosa che forse avete già provato a fare ma la dico lo stesso è usare la JVM server (lanciare l'applicazione con l'opzione -server) e/o distribuire il garbage collector (-XX:+UseParallelGC).
E' possibile che la piattaforma Java che usate stia già girando con questa opzione attivata. Dipende dal sistema operativo perchè la macchina è sicuramente rilevata come server-class (e vorrei vedere :D).
Se un programma è multiprocesso (più JVM per la stessa applicazione) nulla questio: è possibile assegnare almeno una JVM per ogni core e via.Tecnicamente è possibile. Non mi risulta che ci sia una qualche opzione della JVM per fare ciò, ma ad esempio in Win32 è possibile. Ci sono delle API apposite per forzare/impostare su quale/i processore/i un processo/thread può essere eseguito.
Ma se il programma è multithreading (una sola JVM) i diversi Thread possono essere gestiti da diversi core?Questo sicuramente! La cosa tipica per una JVM è quella di "mappare" un Thread su un thread nativo del S.O. E il S.O. è certamente in grado di far andare i thread su core diversi.
ShadowX84
17-07-2007, 17:06
Intanto grazie di nuovo per le risposte, scusate ma adesso sono a fare l'altro lavoro...quindi organizzarmi le idee mi richiede un pò di tempo...
...allora...vediamo un pò....
Il sistema che ho sempre sognato di avere ma che non posso permettermi .... :fagiano:
Guarda...a meggio quando sono arrivati i nuovi server...con tanto di cestelli S.A.S. con dischi da 15.000 RPM nn credevo ai miei occhi, ero appena arrivato e trovarmi davanti tanta roba mi creava delle palpitazioni...ma..a distanza di qualche mese...guarda...meno male che c'è Oracle a impegnare un pò quelle macchine...sennò...credimi...erano veramente sottosfruttate.:rolleyes: (Dal mio punto di vista ovviamente...ma sai..non essendo il sistemista..il mio p.d.v. vale 0)
Il parallelismo, cioè il poter eseguire più operazioni "contemporaneamente", non è una cosa che si può attivare così su due piedi su del codice già scritto. Va pianificato, studiato e verificato attentamente quando si progetta l'applicazione.
Ci sono questioni per nulla banali che riguardano la sincronizzazione tra thread, accesso a risorse condivise, ecc....
Lo so bene, infatti se dovessimo intervenire sul codice ci sarebbe da mettersi le mani nei capelli, cosa che andrà fatta prima o poi...ma prima di qualche mese non possiamo proprio.
Per questo chiedevo se c'erano delle vie alternative, magari anche meno eleganti...e un pò forzate..per tamponare momentaneamente la situazione...:(
E qui mi sorge una curiosità latente e mai soddisfatta.
Se un programma è multiprocesso (più JVM per la stessa applicazione) nulla questio: è possibile assegnare almeno una JVM per ogni core e via.
Che intendi dire?
Ma se il programma è multithreading (una sola JVM) i diversi Thread possono essere gestiti da diversi core?
vedi sopra...:confused: perdonami...ma sono molto molto in erba in quanto a programmazione...
Comunque sia, una cosa che forse avete già provato a fare ma la dico lo stesso è usare la JVM server (lanciare l'applicazione con l'opzione -server) e/o distribuire il garbage collector (-XX:+UseParallelGC).
Ancora non abbiamo fatto nulla...il problema è stato posto solo oggi...:rolleyes:
E' possibile che la piattaforma Java che usate stia già girando con questa opzione attivata. Dipende dal sistema operativo perchè la macchina è sicuramente rilevata come server-class (e vorrei vedere :D).
:D Il server monta una Fedora.
Tecnicamente è possibile. Non mi risulta che ci sia una qualche opzione della JVM per fare ciò, ma ad esempio in Win32 è possibile. Ci sono delle API apposite per forzare/impostare su quale/i processore/i un processo/thread può essere eseguito.
Questo sicuramente! La cosa tipica per una JVM è quella di "mappare" un Thread su un thread nativo del S.O. E il S.O. è certamente in grado di far andare i thread su core diversi.
Quindi?
Grazie di nuovo....;)
Allora, la tabellina di Sun mi dice che su Fedora una Java SE 6 gira come server, per cui il gc è già parallelo.
Giusto per essere sicuri, basta lanciare JConsole e vedere i parametri che riporta nella scheda "VM Summary" (JConsole è incluso nel jdk, si lancia con un jconsole da linea di comando).
Il programma multiprocesso è... due programmi diversi. E' un po' come se anzichè invocare un metodo per salvare del testo su un file tu lanciassi un programma separato per farlo. In questo caso il programma sarebbe multiprocesso.
Limitandosi a fare "new Thread().start()" et similia, il programma è multithread. E' sempre concorrenza ma ad un livello diverso (Thread diversi esistono nello spazio di memoria dello stesso processo).
ShadowX84
18-07-2007, 08:43
Sul server ci gira una Fedora A.S. 4, e la versione della JRE è 1.4.1.
(Onestamente credevo/speravo almeno nel 1.5 )
e/o distribuire il garbage collector (-XX:+UseParallelGC).
Premesso che ancora non abbiamo provato, che cosa cambierebbe concretamente lanciando l'applicazione con "-server"?.
Inoltre: distribuire il garbage collector che cosa comporta?
Mi spiego: L'applicazione iniziaerà ad utilizzare i vari core? Potrebbero subentrare problemi di concorrenza e/ di accessi alla risorse?
^TiGeRShArK^
18-07-2007, 10:10
Sul server ci gira una Fedora A.S. 4, e la versione della JRE è 1.4.1.
(Onestamente credevo/speravo almeno nel 1.5 )
Premesso che ancora non abbiamo provato, che cosa cambierebbe concretamente lanciando l'applicazione con "-server"?.
Inoltre: distribuire il garbage collector che cosa comporta?
Mi spiego: L'applicazione iniziaerà ad utilizzare i vari core? Potrebbero subentrare problemi di concorrenza e/ di accessi alla risorse?
Lìapplicazione lanciata con l'opzione server impiegherà un pò di + a partire e utilizzerà + memoria ma sarà + veloce al runtime.
Parallelizzando il Garbage Collector esso girerà su tutti i core.
Ma il guadagno prestazionale cmq sarà minimo perchè il main thread della tua applicazione girerà cmq su un singolo core.
^TiGeRShArK^
18-07-2007, 10:14
E qui mi sorge una curiosità latente e mai soddisfatta.
Se un programma è multiprocesso (più JVM per la stessa applicazione) nulla questio: è possibile assegnare almeno una JVM per ogni core e via.
Si, ma non ha alcun senso.
Ci penseranno lo scheduler e il dispatcher del sistema operativo ad assegnare i Thread associati alle varie VM (ogni VM ha ben + di un Thread) nei vari core, dinamicamente, a seconda dell'utilizzo richiesto e del carico dei processori.
Assegnare staticamente una VM ad un core quasi sicuramente sarà eno efficiente rispetto a lasciare questa assegnazione al SO.
Ma se il programma è multithreading (una sola JVM) i diversi Thread possono essere gestiti da diversi core?
Ovviamente si.
In java, al contrario di ruby, i thread sono mappati in thread nativi del SO e quindi vengono gestiti in maniera del tutto trasparente dallo scheduler.
ShadowX84
18-07-2007, 10:20
Lìapplicazione lanciata con l'opzione server impiegherà un pò di + a partire e utilizzerà + memoria ma sarà + veloce al runtime.
Parallelizzando il Garbage Collector esso girerà su tutti i core.
Ma il guadagno prestazionale cmq sarà minimo perchè il main thread della tua applicazione girerà cmq su un singolo core.
Sono un pò duro lo ammetto....
Non capiso che vantaggi (anche limitati) potrei ottenere smistando il Garbage sui vari core, se poi comunque il main thread, come hai riustamente riportato tu, contnuerà a girare su un unico core.
^TiGeRShArK^
18-07-2007, 10:25
Sono un pò duro lo ammetto....
Non capiso che vantaggi (anche limitati) potrei ottenere smistando il Garbage sui vari core, se poi comunque il main thread, come hai riustamente riportato tu, contnuerà a girare su un unico core.
avrai solamente dei leggerissimi vantaggi.
L'unico modo x farlo andare + veloce è riscriverlo per il multi-threading.
Non c'è altro da fare.
ShadowX84
18-07-2007, 10:43
avrai solamente dei leggerissimi vantaggi.
L'unico modo x farlo andare + veloce è riscriverlo per il multi-threading.
Non c'è altro da fare.
:stordita: ===> :doh: ===> :muro: ===> :cry:
Lo immaginavo.
Non potendo intervenire così pesantemente nel codice allora mi consigli di intervenire momentaneamente sul Garbage Collector?
Comque sia...grazie...
Non e' detto che un compito sia sempre divisibile tra piu' thread...
Per curiosita' cosa fa il programma quando la prima cpu va al 100%?
(ovvero qual e' il "lavoro pesante"?)
ShadowX84
18-07-2007, 12:35
Non e' detto che un compito sia sempre divisibile tra piu' thread...
Lo so, anche il parallelismo ha dei limiti ;)
Per curiosita' cosa fa il programma quando la prima cpu va al 100%?
(ovvero qual e' il "lavoro pesante"?)
Un esempio può essere la generazione di bolle e fatture (che è una procedura molto corposa).
In pratica vengono generati e stampati i PDF delle bolle e delle fatture (si tratta di qualche migliaio alla volta), ovviamente i dati per l'elaborazione vengo estrapolati da Oracle e quindi come dicevo è un'operazione corposa.
Calcola che questa operazione porta l'utilizzo della CPU al 100% e quindi anche gli altri utenti che devono utilizzare il gestionale (anche per altre funzioni...) risultano rallentate o bloccate.
Quindi presumo che queste fatture, diciamo 1000, vengano generate sequenzialmente
una dopo l'altra? In questo caso dovresti individuare il punto dove viene
avviata la procedura e inserirci un esecutore che smisti in vari thread le varie fatture.
Inoltre questo prog avra' un'interfaccia. Cosa compare mentre viene eseguito tutto questo?
ShadowX84
18-07-2007, 13:18
Quindi presumo che queste fatture, diciamo 1000, vengono generate sequenzialmente
una dopo l'altra? In questo caso dovresti individuare il punto dove viene
avviata la procedura e inserirci un esecutore che smisti in vari thread le varie fatture.
Ok, diciamo che fino a qui ti seguo.
Mi e ti chiedo: così facendo, però mi troverei con un programma enorme singlethread (situazione attuale) ad un programma sempre enorme, strutturato sempre come singlethread con però una procedura adattata all'esecuzione multithread??
Ho inteso bene? Se si, è una cosa fattibile? è salutare? quanto mi potrebbe stravolgere il programma?
Inoltre questo prog avra' un'interfaccia. Cosa compare mentre viene eseguito tutto questo?
Sinceramente non lo so, in quanto la fatturazione viene lanciata da altre sedi e quindi non so che cosa vedano di preciso loro nello schermo.
A quando ne so io, le loro macchine rallentano in attesa che il gestionale porti a termine le operazioni. (a grandi linee...)
Ok, diciamo che fino a qui ti seguo.
Mi e ti chiedo: così facendo, però mi troverei con un programma enorme singlethread (situazione attuale) ad un programma sempre enorme, strutturato sempre come singlethread con però una procedura adattata all'esecuzione multithread??
Ho inteso bene? Se si, è una cosa fattibile? è salutare? quanto mi potrebbe stravolgere il programma?
Il thread principale, invece di processare tutte le fatture sequenzialmente, distribuira'
la computazione tra piu' thread.
Dovresti trovare la parte di codice incriminata, e cercare di estrarre la parte
che processa una singola fattura in un Runnable, che poi passerai a un esecutore,
ad es. nel vostro caso (8 core) potrebbe andare bene un
Executor executor = Executors.newFixedThreadPool(8);
che come puoi leggere dalla documentazione
http://java.sun.com/javase/6/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool(int)
usa 8 thread per processare i task, accodati con ad esempio:
executor.execute(task);
Ovviamente in queso caso il thread principale non si blocchera' ad attendere che
i task siano terminati, quindi bisogna stare attenti...
Per quanto riguarda le prestazioni dei vari tipi di pool dovresti sentire qualcuno
che ne sa di piu', magari un pool "cached" e' piu' performante, non so...
Portare un programma da single thread a multithread non è una passeggiata. Non perchè non sia facile farlo in Java. Diavolo, i Thread son lì che ti quasi ti sorridono. Il problema è che una cosa che funziona in un contesto a thread singolo non è detto che funzioni con due. Cose piccole. Un assegnamento, un'inizializzazione. Occorre un'analisi "statica" del codice, non difficile ma lunga e noiosa. Occhi aperti.
Stando a quanto dichiara Sun, la macchina virtuale server è una JVM diversa da quella client. L'unica diceria concreta è che la JVM server esegue il loop unrolling mentre la JVM client non lo fa. Poi si parla di una resa migliore dell'allocazione e deallocazione per oggetti di grandi dimensioni.
Da profano (non ho mai guardato il codice della JVM... ok, l'ho guardato ma non l'ho mai capito :D) penso che una ragione se usano la versione server per i benchmark delle applicazioni server ci sarà.
http://blogs.sun.com/dagastine/
In ogni caso provare non costa nulla. Anzichè lanciare il programma con java eccetera lo lanci con java -server eccetera. E vedi cosa succede.
Potresti anche provare il JRE di BEA. E' ottimizzato per piattaforme intel (sempre a detta di BEA).
Insomma, prima di mettere le mani nel codice io proverei le strade non invasive. Anche un test con Java 6. Potresti avere problemi con le librerie XML (da 1.4 a 5 sono cambiate alcune opzioni predefinite del parser, è possibile che un documento XML precedentemente accettato ora sputi un "content is not allowed in prolog") e altri intoppi minori che al 99% per cento sono risolvibili dall'esterno.
mi permetto di segnalarvi queste 4 guide scritte da un amico riguardanti il multi-threading
http://www.codicefacile.it/tutorials/tutorials.php/21/Cenni+di+programmazione+multi-threading
http://www.codicefacile.it/tutorials/tutorials.php/22/Cenni+di+programmazione+multi-threading+-+parte+2
http://www.codicefacile.it/tutorials/tutorials.php/39/Cenni+di+programmazione+multi-threading+-+parte+3
http://www.codicefacile.it/tutorials/tutorials.php/41/Cenni+di+programmazione+multi-threading+-+parte+4
AnonimoVeneziano
16-02-2008, 19:45
Mmm, attenzione a far diventare multithread un programma che fa molte operazioni di IO (letture dal disco).
A quanto ho capito il programma legge da database oracle i dati. Oracle ovviamente i dati li va a prendere dall'HD , quindi c'è il rischio che se 8 thread (nel caso del tuo server a 8 core) tentano di leggere contemporaneamente dall'HD tu possa finire per avere un rallentamento piuttosto che un aumento di velocità, perchè la testina dell'HD non legge più sequenzialmente i dati, ma continua a saltare da un punto all'altro dell'HD per soddisfare le richieste degli 8 thread che vogliono i dati.
La prova l'ho fatta io personalmente facendo diventare multithread un programma che avevo scritto che elaborava diversi files dall'HD. Con 2 thread ci metteva praticamente il doppio del tempo che con uno solo.
Con un solo thread usava un Core al 100% e l'altro stava all'asciutto. Con 2 thread entrambi i Core lavoravano a circa il 10-20%. Questo significa che l'applicazione era diventata IO-Bound
Ciao
Un esempio può essere la generazione di bolle e fatture (che è una procedura molto corposa).
In pratica vengono generati e stampati i PDF delle bolle e delle fatture (si tratta di qualche migliaio alla volta), ovviamente i dati per l'elaborazione vengo estrapolati da Oracle e quindi come dicevo è un'operazione corposa.
Calcola che questa operazione porta l'utilizzo della CPU al 100% e quindi anche gli altri utenti che devono utilizzare il gestionale (anche per altre funzioni...) risultano rallentate o bloccate.
Il programma è client/server strutturato in che modo?
client con una GUI swing e server che esporta funzioni con RMI?
oppure applicazione web-based?
Che libreria usate per generare i PDF?
Avete il codice dell'applicazione?
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.