PDA

Visualizza la versione completa : [java] elementi sincronizzati


rinosan_76
10-12-2003, 01:02
CIao a tutti, ho un problema che è sicuramente più difficile per me da spiegare che per voi da realizzare...
Provo a semplificarlo.
Io ho creato una classe con vari metodi di cui uno che prende da un DB dei dati; questo metodo ritorna un oggetto contenente i dati.
Vorrei dividere la cosa... vorrei che un metodo mi prenda i dati e me li metta nell'oggetto, e poi quando mi servono con un altro metodo posso andare a leggere l'oggetto. Naturalmente non devo poter leggere l'oggetto prima dell'inserimento dei dati in esso. So che si usano tread sincronizzati, ma questa parte dei tread non mi è ancora molto chiara.
Se potreste farmi un esempio anche solo con un metodo che mi fa una somma ve ne sarei grato.
Ciao
Rino

rinosan_76
10-12-2003, 13:06
...nessun aiuto?

cristiano_longo
10-12-2003, 16:03
Da come la poni i thread non centrano nulla. Semplicemente quando leggi salvi il contenuto in un attributo e crei un metodo che restituisca il valore di quell'attributo.

A meno che tu non stia parlando di servlet ...

LeleFT
10-12-2003, 18:22
I thread a cui ti riferisci in questo contesto sarebbero i famosi Lettori e Scrittori (un bel problemino conosciuto!). Se vuoi un esempio di programma che faccia uso di un thread lettore e di uno scrittore non c'è problema, te lo posto in calce al messaggio, però, come dice cristiano_longo, in questo caso particolare non ti sono di grande aiuto. In genere, questo tipo di thread si comportano in questo modo: lo scrittore scrive in un buffer e se questo è pieno, si blocca e attende; il lettore legge dal buffer e se questo è vuoto, si blocca e attente. Per quello che devi fare tu non credo sia di aiuto (né necessario) che il thread lettore si blocchi se il thread scrittore non ha ancora scritto i dati nel buffer (ossia non li ha ancora letti dal DB). In questo caso dovresti decidere come comportarti: vuoi far sì che quando avviene una richiesta di lettura un thread si occupi della lettura e fornisca i dati, oppure a te serve che un thread legga in continuo i dati dal db, li metta in un buffer e attenda che il lettore li consumi?

Questo è un esempio di problema dei Lettori / Scrittori:


public class Buffer {
private int [] buffer;
private int first;
private int last;

public Buffer() {
buffer = new int[10]; // limito il buffer a 10 elementi
first = last = 0;
}

public synchronized void aggiungiElemento(int elemento) {
if (last == 9) { // il buffer è pieno...
try {
wait(); // ...attendo che il lettore consumi almeno un elemento
} catch (Exception e) {}
}
last++;
buffer[last] = elemento; // aggiungo l'elemento al buffer
notify();
}

public synchronized int leggiElemento() {
int tmp;
if (last == 0) {
try {
wait();
} catch (Exception e) {}
}
tmp = buffer[0];
shiftaElementi();
last--;
notify();
return tmp;
}

private void shiftaElementi() {
for (int i=0; i<9; i++) buffer[i] = buffer[i+1];
buffer[9] = 0; //non necessario...
}
}

public class Lettore extends Thread {
private Buffer b;
private int valore;
private int somma;

public Lettore(Buffer b) {
this.b = b;
valore = somma = 0;
}

public void run() {
while (true) {
valore = b.leggiElemento();
somma += valore;
System.out.println("Ultimo valore letto: " + valore);
System.out.println("Somma attuale: " + somma);
}
}
}

public class Scrittore extends Thread {
private Buffer b;
private int valore;

public Scrittore(Buffer b) {
this.b = b;
valore = 0;
}

public void run() {
while (true) {
valore = ((int)((Math.random() * 500000) % 64; // genero un numero a caso fra 0 e 63
b.aggiungiElemento(valore);
}
}
}

class Programma {
public static void main(String [] args) {
Buffer b = new Buffer();
Lettore l = new Lettore(b);
Scrittore s = new Scrittore(b);
s.start();
l.start();
}
}


Ciao.

rinosan_76
11-12-2003, 12:36
Grazie gli do una occhiata e poi vi dico se ho capito.

rinosan_76
11-12-2003, 15:44
l'ho guardato e devo ammettere che può servire, ma non so se fa al caso mio, quindi ti ripropongo il problema per vedere se è utilizzabile il tuo codice.
Ho un metodo che chiama un altro il quale normalmente impiega 10-15 secondi almeno per dare il risultato da inserire in un oggetto. Nel frattempo ho un altro metodo che invece vurrebbe subito leggere l'oggetto trovandolo non aggiornato, come posso far si che quest'ultimo aspetti? Ho capito che nel tuo codice c'è un qualcosa di simile... ma vorrei me lo spiegassi...
Grazie Rino

LeleFT
11-12-2003, 17:02
Per poter applicare il metodo del Lettore / Scrittore devi trasformare i due metodi in due thread (due classi diverse). Questi due thread si devono sincronizzare su un buffer (una terza classe). E' questa terza classe che dice ai due thread quando fermarsi (nel tuo caso, dovrebbe dirlo al lettore).
Dovresti far sì che il metodo che legge dal DB, una volta trasformato in thread, vada a scrivere i dati sul buffer (devi dimensionare il buffer in modo da riuscire a contenere tutti i dati che gli passa), quindi i dati dovrebbero essere memorizzati in un vettore (un array, oppure la classe Vector dovrebbero andare bene) all'interno della classe che fa da buffer.

Quando il lettore (quello che attende i dati) vuole leggere dal buffer, il buffer controlla se ci sono dei dati. Se ci sono dei dati glieli restituisce, altrimenti chiama il metodo wait() che blocca il thread finchè non riceve un notify().

Quando lo scrittore scrive sul buffer, è necessario che venga invocato il metodo notify(): se c'è il thread lettore in attesa, infatti, bisogna risvegliarlo; se non c'è il thread in attesa, il notify() viene semplicemente perso (ignorato).


Ciao.

rinosan_76
11-12-2003, 17:07
essendo che la risposta è una il buffer può essere dimensionato a 1? o devo fare qualcos'altro?

LeleFT
11-12-2003, 17:25
Certamente. Il buffer può essere anche solamente una variabile. Ma da quel che avevo letto, i dati dovevano provenire da un DB e di solito le interrogazioni su un DB portano ad avere anche più di un record. Nel caso la tua interrogazione restituisca solamente un record avrai bisogno, comunque, di più di una variabile per contenere tutti i campi di quel record, nel caso, invece, l'interrogazione produca un solo valore, la variabile singola va benissimo.

Un buffer non è necessariamente un contenitore di molti dati, può contenere anche un solo dato alla volta.


Ciao. :ciauz:

rinosan_76
12-12-2003, 11:20
ok proverò a fare le modifiche...

Loading