Threads y Sincronización
El JNDI define acceso síncrono a los sistemas de nombres y directorios. La
igual que la mayoría de los APIS definidos para la plataforma Java, el acceso
asíncrono se consigue usando varios threads.
Cuando usamos varios threads en nuestro programa, debemos recordar que el
JNDI especifica que en los accesos concurrentes al mismo ejemplar Context
no está garantizado que sean seguros ante los threads. Aunque algunos
proveedores de servicios podrían garantizar la seguridad ante los threads para
el mismo ejemplar de Context, es mejor usar sincronización para
que el código sea portable a diferentes implementaciones de proveedores de
servicios. Cuando usamos varios threads para acceder a diferentes ejemplares de Context,
no necesitan estár sincronizados.
Aquí tenemos un ejemplo que crea dos threads,
cada uno lista un ejemplar distinto de Context:
// Create the contexts
Context ctx1 = new InitialContext(env);
Context ctx2 = (Context)ctx1.lookup("ou=People");
// Create the threads
Thread thread1 = new ListThread(ctx1, "ONE");
Thread thread2 = new ListThread(ctx2, "TWO");
// Let them work
thread1.start();
thread2.start();
El método run() de cada threads e parece a esto.
public void run() {
try {
NamingEnumeration enum = ctx.list("");
while (enum.hasMore()) {
System.out.println(label + ": " + enum.next());
}
} catch (NamingException e) {
System.out.println(label + ": " + e);
}
}
Cuando ejecutemos este programa, veremos la siguiente salida.
# java DiffCtx
ONE: ou=Groups: javax.naming.directory.DirContext
ONE: ou=People: javax.naming.directory.DirContext
ONE: ou=Staff: javax.naming.directory.DirContext
ONE: ou=NewHires: javax.naming.directory.DirContext
TWO: cn=Ted Geisel: javax.naming.directory.DirContext
ONE: cn=favDrink: javax.naming.directory.DirContext
TWO: cn=Jon Ruiz: javax.naming.directory.DirContext
TWO: cn=Scott Seligman: javax.naming.directory.DirContext
...
Observa qua a pesar del echo de que ambos ejemplares de Context
están derivados del mismo ejemplar InitialContext, no
necesitamos bloquear sus accesos. Sin embargo, si modificamos ligeramente el
ejemplo para poder usar dos threads que listen el mismo Context,
necesitamos bloquear el ejemplar de Context. En el siguiente programa
modificado, el método run() del thread se parecería a
esto.
public void run() {
try {
// Lock for multithreaded access
synchronized (ctx) {
NamingEnumeration enum = ctx.list("");
while (enum.hasMore()) {
System.out.println(label + ": " + enum.next());
}
}
} catch (NamingException e) {
System.out.println(label + ": " + e);
}
}
Cuando ejecutemos este ejmplo, generará la siguiente salida.
# java SameCtx
ONE: ou=Groups: javax.naming.directory.DirContext
ONE: ou=People: javax.naming.directory.DirContext
ONE: ou=Staff: javax.naming.directory.DirContext
ONE: ou=NewHires: javax.naming.directory.DirContext
ONE: cn=favDrink: javax.naming.directory.DirContext
TWO: ou=Groups: javax.naming.directory.DirContext
TWO: ou=People: javax.naming.directory.DirContext
TWO: ou=Staff: javax.naming.directory.DirContext
TWO: ou=NewHires: javax.naming.directory.DirContext
TWO: cn=favDrink: javax.naming.directory.DirContext