Newsgroup: it.comp.java
Titolo: Queue

Ho bisogno di *accodare* degli oggetti e recuperarli successivamente
nel medesimo ordine temporale. Alla bisogna ho scritto questa classe
Queue, vorrei sapere se:
- Esiste qualcosa di già scritto?
- Come la ho implementata io garantisce l'ordine temporale (ai miei
test risulterebbe di si)?
- Si può ottimizzare in qualche modo (più per curiosità che per
necessità...)
[SOURCE Queue.java]
import java.util.Vector;
public class Queue
{
	private Vector buffer;
	private Object next;
 
	public Queue()
	{
		buffer=new Vector();
	}
 
	public Object get()
	{
		if(buffer.size()>0)
		{
				next=buffer.get(0);
				buffer.remove(0);
				return next;
		}
		return null;
	}
 
	public void add(Object obj)
	{
		buffer.add(obj);
	}
}
[/SOURCE]
TIA,
Mauri.
 
-- 
La forza di gravità è un falso mito,
è la Terra che succhia!

On Mon, 22 Oct 2001 11:43:05 GMT, 
avant...@inwind.it
 (Maurizio
Testa) wrote:
perfetto: infatti i Vector grazie ad add e remove si comportano
flessibilmente sia come FIFO(code) che come LIFO(pile)
ciao


Okay, dopo una velocissima occhiata direi che next non ha bisogno di fare parte dello
stato dell'oggetto e che se usi questa classe in ambiente multithreading ti conviene
sincronizzare le operazione size / get / remove sul vettore (fra l'altro la remove() ti
torna l'elemento rimosso). Quindi:
public class Queue
{
    private Vector buffer;
 
    public Queue()
    {
        buffer=new Vector();
    }
 
    public Object get()
    {
        Object next = null;
        synchronized(buffer)
	{
	    if(buffer.size()>0)
            {
                next=buffer.remove(0);
            }
        }
        return next;
    }
 
    public void add(Object obj)
    {
        buffer.add(obj);
    }
}
Ciao,
    Bruno.
On Mon, 22 Oct 2001 11:43:05 GMT, 
avant...@inwind.it
 (Maurizio Testa) wrote:

|
| Bruno Bossola
| A Java Software Engineer :-)
| 
http://bbruno.fasturl.it
|
| 
http://members.xoom.it/bbruno
| 
http://digilander.iol.it/bbossola
|

stato dell'oggetto 
Grazie per tutto.
Mi è chiara la questione di remove() che non avevo visto, giustissimo
anche il synchronized... spiegami meglio quella di next e dello stato
(sono pooooooco dopo le prime armi...)
Danke schoen,


č la Terra che succhia!


torna l'elemento rimosso). Quindi:
[CUT]
Non sono un esperto in materia, ma dal codice vedo che i metodi
add/get/get/remove di Vector sono già sincronizzati, mentre size no.
HTH
-- 
Ciao
	Fabrizio C.



Non capisco. La size() di Vector non e' sincronizzata per una precisa decisione in fase di
design del team di sun, condivisibile per certi aspetti (ma comunque in quelle classi ha
fatto parecchie schifezze :-D)
In questo caso bisogna analizzarne il comportamento nel contesto specifico: forse non e'
chiaro il problema che sussiste in un ambiente multithreading, cerco di spiegarmi meglio. 
Quando fai questo:
        synchronized(buffer)
	{
	    if(buffer.size()>0)
            {
                next=buffer.remove(0);
            }
        }
richiedi esplicitamente il monitor di buffer (il vector) prima di andare ad indagare sulla
dimensione e poi a rimuovere l'elemento. Il fatto che noi impegniamo il monitor di buffer
nell'intero periodo di tempo impedisce a chiunque altro di andare ad rimuovere qualcosa
nel mentre. 
Se infatti lo scriviamo cosi...
	    if(buffer.size()>0)
            {
                next=buffer.remove(0);
            }
...potrebbe succedere questo:
Il thread A e il thread B stanno entrambi per operare una remove(). Il thread A richiede
la dimensione del buffer, che in quel momento e' 1: procederebbe quindi a rimuovere
l'elemento, ma in quell'istante il controllo passa al thread B: anche lui verifica la
dimensione, che e' 1, procede quindi a rimuovere l'elemento e lo fa. A questo punto il
thread A riprende il controllo, fa per rimuovere l'elemento e... eccezione! L'elemento non
c'e' piu', gia' rimosso dal thread B. E' chiaro lo scenario?
Invece se li costringi a sincronizzarsi sul monitor del buffer per il tempo necessario,
come ho proposto, tutto questo non succede e l'oggetto funziona anche in ambiente
multithreading. 
Ciao,
    Bruno.


E' chiaro lo scenario?
Sì, forse avevo letto un po' troppo superficialmente.
Vediamo se ho capito _del_tutto_ quello che dici (corretamente) tu.
Il fatto che Vector abbia i metodi sincronizzati non garantisce la
coerenza di Queue (il cui stato non *coincide* con il Vector).
L'uso di
synchronized(buffer)
*qui* è l'equivalente di dichiarare synchronized il metodo get di
Queue.
Sbaglio?
Allora, potendo, perché non usare un altra struttura più "leggera"
(tipo ArrayList) al posto di Vector? Ci sono controindicazioni?
Grazie e a presto.
PS
Una volta non c'era la convenzione di chiamare queue e dequeue i
metodi in questione (come pop e push per gli stack)? E' solo un
ricordo del Pascal?
-- 
Ciao
	Fabrizio C.


Mah, diciamo che anche io concordo sul fatto che i nomi dovrebbero essere piu' speaking, e
quindi queue e dequeue sono sicuramente due nomi piu' appropriati. 


loro interno la sincronizzazione.
Direi che non č proprio stata gestita. Anzi, č meglio dire che č stata
gestita molto diversamente.
Cito dal Tutorial.
Problem: Are Hashtables synchronized in Java 2 (formerly known as JDK
1.2)? 
Yes, Hashtables are still synchronized in Java 2. The fact that the
new implementations in Java 2 are unsynchronized represents a break
with the past: Vector and Hashtable were synchronized in versions of
the JDK prior to 1.2. In other words, legacy collections (like Vector
and Hashtable) are synchronized, whereas new collections (like
ArrayList and HashMap) are unsynchronized, and must be "wrapped" via
Collections.SynchronizedList or Collections.synchronizedMap if
synchronization is desired.
Grazie dei chiarimenti.
-- 
Ciao
	Fabrizio C.


Come dicono a Milano, grazie a te :-D
(Ah, io ora sono a Torino)
