PDA

Visualizza la versione completa : [java] Runnale&Thread


maurizio2
20-03-2005, 14:00
In quali occasioni in java viene utilizzato il
multithreading?
:ciauz:

netarrow
20-03-2005, 14:23
per far fare ad un programma più cose contemporaneamente.
Ad esempio, un clientmail è un processo che è indipendente con emule che scarica e l'antivirus che controlla, i processi sono residenti in percorsi di memoria totalmente diversi, quindi un processo(sarebbe un programma) è l'unità fondamentale del sistema operativo, un thread invece è l'unità fondamentale del programma stesso, più thread stanno nello stesso spazio di memoria, è più semplice comunicare fra thread che fra processi(dove bisogna utilizzare pipe o socket), solo che ci sono problemi di sincronizzazione con i thread.
Ritornando al cliuentmail, un thread è ad esempio quello che ti permette di spedire la posta mentre tu scrivi un mail e mentre il client ne sta ricevendo un'altra.
Se tutto fosse in un unico thread il programma si bloccherebbe:



|
|
|
Manda mail
|
|(solo quando le mail saranno mandate)
Ricevi mail

ecc...


col thread l'azione di manadre una mail si stacca e continua cmq l'esecuzione.
In un pezzo di codice java ad esempio se scrivi

metodo1()
metodo2()

metodo 2 verrò chiamato solo quando metodo1 avrà completamente finoto di fare quello che doveva, se metodo1 fosse un metodo start(che fa partire un thread), appena il thread parte metodo2 e tutto il codice successivo verrà eseguito in contemporanea.

Un altro esempio è la chat, per ogni utente connesso il server crea un thread che gestirà l'utente connesso in contemporanea con gli altri.

:ciauz:

maurizio2
20-03-2005, 14:47
Certo l'argomento e' complesso ma sostanzialmente
i thread suddividono il main()(thred principale)
in "mini programmi",
quindi da un punto di vista gerarchico abbiamo cosi:
OS-->threads delle applicazioni-->threads di una applicazione.

Ma mi chiedo adesso una cosa, io ho realizzato un simulaore
softwere dove le istruzioni si trovano all'inizio della
memoria e i dati a partire dalla fine a ritroso,
Fa cosi anche la RAM di un pc o i dati di ogni applicazione
vengono spostati subito dopo le istruzioni??

Memoria simulatore:
--->
istruzioni------------------dati
cosi nel mio simulatore ogni programma impegna tutta la memoria
e non potrei mai simulare il multithreading.

dekdek
20-03-2005, 16:00
In genere il sistema operativo associa due o piu' aree di memoria ad un processo.
Di certo c'e' un'area codice: siccome puo' essere condivisa da diverse istanze dello stesso programma (multiprocessing) non dovrebbe contenere dati.
Quindi c'e' un'area dati, di solito divisa in stack ed heap: di questo puo' occuparsi il compilatore a tempo di compilazione. (Ovviamente se ci sono piu' aree dati il problema non si pone...)
Nello stack vengono impilate le variabili locali del blocco in esecuzione, in modo che il ritorno dalla funzione invocata non comporti la loro cancellazione: basta riportare lo stack pointer al valore precedente. E' un po' confuso come l'ho spiegato in effetti... Ma gugolando un po:

basta osservare come si muove la cima della stack (http://www-ee.eng.hawaii.edu/Courses/EE150/Book/chap14/subsection2.1.1.8.html)

Nello heap vanno le variabili statiche, o cmq tutto cio' la cui visibilita' non e' limitata al blocco in esecuzione.

Resta il problema dell'allocazione dinamica. A questo scopo credo che ogni linguaggio, se non ogni compilatore, provveda a suo piacimento.
Girando un po' vedo che anche l'area designata all'allocazione dinamica viene chiamata heap, ed in effetti potrebbe coincidere con lo heap...

maurizio2
20-03-2005, 16:16
Quindi al mio simulatore dovrei implementare una funzione
che conta tutte le istruzioni i dati e tenere traccia
di dove essi sono collocati nella memoria in modo tale
da essere in grado di mettere in esecuzione un altro
programma, e poi una funzione che simula lo schedulatore
per assegnare il processore a uno o all'altro programma.
Ma cmq mi chiedevo ccome il sistema gestisce la memoria
se da ambo le estremita' della memoria o a partire
dall'inizio.

dekdek
20-03-2005, 16:22
La soluzione che ricordo e' quello con lo heap che parte dal principio dell'area dati e lo stack che, partendo dalla fine, sfrutta tutto il resto dello spazio.
Per il resto... Non mi sono mai addentrato nei dettagli, ma c'e' tutto un insieme di fattori che determinano il modo in cui le variabili vengono allocate. Per esempio, il compilatore deve generare codice rilocabile, che non accede direttamente alla memoria. Poi, dovra' esserci un loader che interpreta l'eseguibile ed, in base allo stato del sistema, gli assegna le aree di memoria di cui necessita per l'esecuzione.

P.S. Non prendere tutto cio' che dico per oro colato... Sono un pochino arruginito su questi argomenti e necessiterei una ripassatina, per cui la vongola puo' scapparci! :D

maurizio2
20-03-2005, 16:30
Dai non ti preoccupare :)
Sto cercando di capire i Thread in java aldila'
del codice....
Ho studiato tutto il C ma non ho approfondito la cosa
con le API, dovrei studiare anni per poi realizzare
una semplice applicazione con le GUI di sistema e ho buttato
la pezza!! E sono passato in java anche se vasto ma piu'
abbordabile(sotto certi punti di vista).
:ciauz:

dekdek
20-03-2005, 17:00
Allora, per quel poco che ne so...

I thread possono essere gestiti in due modalita': dal SO, o dall'utente.

Se il sistema operativo si occupa della gestione, tutto e' trasparente per l'utente, che deve solo richiamare le primitive messegli a disposizione (tramite apposite interfacce fornite dal linguaggio di programmazione)
Lo svantaggio di questa soluzione e' che il sistema operativo:
a) deve memorizzare informazioni su ogni thread, anziche su ogni processo, rendendo piu' oneroso lo scheduling;
b) deve essere continuamente interpellato per decidere quale thread deve essere eseguito, creando overhead, spreco di tempo: infatti, laddove ci sarebbe la possibilita' di eseguire un altro thread dello stesso processo, sono invece obbligato a interrompere il mio programma, interpellare il SO, il quale fara' lo scheduling (che come abbiamo detto ora e' anche piu' oneroso...) per decidere cosa eseguire, e poi si interrompera' a sua volta per mandare in CPU il thread schedulato;
c) detto questo, bisogna prevedere uno scheduling "equo": se i thread venissero gestiti separatamente, un processo con 100 thread avrebbe cento volte in piu' possibilita' di essere schedulato!

Se l'utente gestisce i thread, non solo puo' decidere da solo quale mandare in esecuzione, ma puo' farlo secondo una politica che puo' differire del tutto da quella adottata dal sistema operativo: ad esempio puo' dare sempre maggiore priorita' ad alcuni thread anziche' altri, laddove il SO prevederebbe l'alternanza "equa" dei processi nella CPU.
Tutto cio' senza cambiare il contesto di esecuzione, visto che i thread condividono sia l'area codice che l'area dati.

In questo secondo caso, se il SO non prevede il supporto dei thread vede l'insieme dei thread (il task) come un unico processo: cio' e' limitativo perche' se un thread si blocca (per esempio potrebbe aver richiesto l'accesso al disco al sistema operativo) si ferma tutto il task!!! Questo perche' il SO non e' in grado di discernere fra un thread e l'altro: sa che quel processo ha richiesto un servizio (es. accedere al disco), sa che non l'ha ancora ottenuto, ergo quel processo non va schedulato fino a quando non esce dallo stato di attesa. Questo problema non ricordo come si risolve... Pero' si risolve!!! ^__^

Veniamo a noi.
In Java i thread sono tecnicamente gestiti dall'utente, dove pero' l'utente e' la Java Virtual Machine che sbriga tutte le rogne che ti ho elencato ed altre ancora!
A te non resta altro che definirli, farli partire, sincronizzarli... Sembra niente! :D

maurizio2
20-03-2005, 19:30
Devo ammettere che mi hai tolto tante rogne con
la tua spiegazione!!
Quindi se dovessi affrontare il problema con un C++
la cosa e' molto complessa perche' accedo direttamente alle
primitive di sistema, invece java mette una bella maschera
di porcellana ad un rospo!!
Allora adesso veniamo un po' al codice...
Ho visto diversi esempi di come spiegare e utilizzare i thread
in java, come ad sempio estendere Thread alla
classe contenente il main() e creare oggetti che cmq
hanno un solo metodo run(), oppure implementare Runnable
sempre alla classe contenente il main() e passare i relativi
oggetti al costruttore Thread() anche in questo caso
abbiamo un unico run().
Quello che piu' ho ritenuto consono relativamente all'impiego dei
thread e' quello di creare sottoclassi di Thread e ogni classe
ha il suo metodo run() e poi con tutti i mezzi messi a
disposizione da java li fai interagire qualora concorrano
ad una risorsa condivisa.
Bhe se ho detto qualcosa che non va ti prego correggimi!!
:ciauz:

dekdek
20-03-2005, 19:47
Coi Thread, ho notato, la cosa migliore e' sperimentare... Perche' cose che dovrebbero funzionare sulla carta poi potrebbero rivelarsi sbagliate!
Ad esempio, i controlli del set Swing creano casini se piu' thread cercano di accedervi contemporaneamente. Ho letto diverse spiegazioni a riguardo, ma ancora non ho capito bene in cosa consiste il problema, ma se dovessi avere il mio stesso problema, ho risolto con la classe SwingWorker3 scaricabile e utilizzabile liberamente dal sito Sun.
Se cmq devi solo operare su dati, si', l'unica cosa di cui ti devi preoccupare e' la gestione dell'accesso ai dati, e la sincronizzazione: nonostante esista la funzione stop(), analoga di start(), ne viene deprecato l'utilizzo, incoraggiando, se possibile, la ricerca di un modo alternativo per i thread di sincronizzarsi.

Loading