forma correcta singleton

como seria la forma correcta de implementar un singleton, cuando digo forma correcta es teniendo en cuenta todo el tema de hilos y concurrencia.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de Sr. Negativo

Forma correcta del Singleton

Aquí hay un ejemplo de crear un Singleton (inglés)

La solucion Bill Pugh saca

La solucion Bill Pugh saca provecho de la forma en la que se cargan las clases en Java

Y tiene la ventaja que es threadsafe y crea el singleton hasta que se requiere ( de forma 'lazy' )

Antes de que lo implementes asegurate que lo necesitas, aunque hay usos legitimos del Singleton puede ser que tambien lo estes queriendo usar en forma de antipatron.

Revisa esta respuesta:

recomiends esto

esta es una palntilla que recomiendan
no se con esta plantilla tenga problemas con mi listener en java (spluciones multihilos)
 

estoy extendiendo un runnable de un singleton

Mi pregunta es saber si con este singleton asi como esta no tendria problemas en la web. me refiero a problemas de concurrencia que la trama de informacion no se me vaya alterar de una u otra forma.
ya que el aplicativo va a correr con un java web start.

 

Primer comentario, regresa al

Primer comentario, regresa al estilo de Java de poner la llave que abre en la misma linea.
 

Aunque parece menor, seguir la convención permite leer mas fácilmente el código.

La idea del singleton es que no tengas que usar variables de clase, entonces no hay razón para tener socket, buffer input y out como tales. Deberían de ser variables de instancia del singleton ( que a su vez es una variable de clase en si mismo ).

Una aplicacion webstart es una aplicación cliente y como tal no tendrías problemas pues solo habría un hilo corriendo, a menos que en tu aplicación crearas multiples hilos, entonces si tendrias problemas porque vas a hacer que dos hilos escriban al mismo lugar ( la variable out ). De hecho al hacerlo singleton y/o variable de clase garantizas tener problemas ( no tendrías problemas si fueran variables de una función ) Y tendrías que sincronizar el acceso a la variable compartida lo cual complica el código y es mas propenso a errores.

Antes de seguir sospecho que quieres optimizar una solución algo que quiza puede hacerse de otra forma asi que la pregunta es: porque quieres usar un singleton? Que beneficio buscas al usar un singleton?

Un singleton ayuda a simplificar la programación al permitir al acceso a un objeto que por su naturaleza en la aplicación es único, por ejemplo, el sistema de archivos.

Porque no abres una conexiona cada vez que quieras mandar un mensaje y/o por cada hilo que tengas? Asi no tendrías ningún problema de corrupción de datos porque cada cliente va a tener solo un canal para comunicarse.

De nuevo, quizá haya mejores formas, pero antes habría que saber que es lo que quieres hacer.

Saludos.

ok

es un programa cliente que se va a comunicar con mi servidor(Listener en java) que maneja un pool de conexiones, por ahora el server trabaja de los mas de bien. la idea del singlenton es tener como todo a mano en cualquier lugar osea la idea es hacer algo que no solo me ayuda a mi sino a los otros desarrolladores que quieran hacer un programa que se comunique con el listener en java; con el singleton buscaba hacer la conexion, enviar la informacion al server y recibir dicha informacion del server (y tener dicha respuesta disponible globamente en la clase que la necesite usar.) y finalmente cerrar conexion. para cualquier desarrollador que necesite enviar info al server java y recibir una respuesta lo usara atraves de esa clase singlenton.

si hay una alternativa mucho mas profesional y mas optima de como hacerlo seria genial que me lo indicaras.
saludos desde colombia.

Aja, pero y porque como

Aja, pero y por que como singleton y no como una clase normal?

 

Que es lo que buscas del singleton?

singlenton

que fuera una unica instancia y que al hacer la peticion el cliente la respuesta que me envia el server la tengo ahi siempre disponible, como si fuera una variable global.

actualmente lo que hago es que desde todas las aplicaciones cliente desde el controler le agrego una clase interna
ListenerSocket la idea es hacer una clase generica que todas mis aplicaciones clientes la usen para enviar y recivir la info del servidor
y no que cada aplicativo en su controler le añada la clase ListenerSocket. la idea con el singleton aparte de tener una sola instancia era que el se encargara de enviar y recivir los dastos del server y yo lo usura en cualquier lado como si de una variable global se tratase.
 

Son dos partes separadas.

Son dos partes separadas. Hacer una clase y distribuirla en una bibliioteca esta genial, no solo no tienen que escribir desde el inicio la logica, sino que ademas se benefician de las mejoras que se hagan.

Que esa clase tenga que ser un singleton es otra cosa. Puede ser un singleton en el sentido en el que solo hay un canal de comunicacion y se obtiene desde un solo punto:
 

Pero aun pueda mandar varios mensajes a la vez. En la implementacion que tienes al usar una variable de clase para "out" tendrias el problema que si tu aplicacion manda dos mensajes a la vez, el mensaje llegara mezclado. Para evitarlo puedes hacer que tu singleton cree una conexion cada vez o encole los mensajes. En servidor tiene un solo socket server, pero puede tener varios sockets clientes, no deberia de haber razon por la cual tu cliente tuviera solamente una conexion.

ok

descartemos el singlenton creo que lo pende erróneamente al verlo como un acceso global.
la idea de todo es que el los aplicativos clientes tenga una especie de clase re utilizable para cualquier aplicativo java que le maneje el envió y recepción de los datos. la idea es evitar en cada programa cliente el ejemplo que te mostré anteriormente como lo trabajo con una clase anidada.

eso que comentas que se mezclan datos seria garrafal, ya que son como 1500 usuarios conectandose al aplicativo cliente.
por lo genereal lo que hago siempre en conectarme enviar datos al sever , el server me responde y termino conexion tomo esos datos que me llegaron del server los procesos y envio otra vez peticion al server en una nueva conexion recivo respuesta del server y cierro
por lo general la idea es que el server responda y se libere.

server timeout

actualmente mi servidor maneja un timeout de 40 seg, la idea es bajarlo a 7 o 5 seg ya que manejo todo por demanada cliente se conecte envia a alserver server responde y se termina la conexion con esa info del server el cliente hace lo que tiene que hacer y envia nueva peticion al server.

El singleton es por JVM, si

El singleton es por JVM, si tienes 10 programas corriendo en 10 JVMs diferentes tienes un singleton distinto en cada programa. Lo mismo si tienes 1,500 usuarios con una aplicacion, hay 1,500 "singletons" diferentes. El concepto aplica solo a nivel programa dentro de una JVM.

La idea del singleton no esta mal, pero en su implementacion puedes usar internamente varias conexiones o crear distintos mensajes, ni tiene porque usar uno solo el mismo. De esa forma sigues teniendo un solo punto de acceso para enviar mensajes y nadie tiene que reinvertar la solucion cada vez.

Imagen de ezamudio

serializable?

Digo ya leí lo demás y veo que has llegado a la conclusión de desechar el singleton; bien. Pero es que leí el primer comentario y lo primero que me saltó a la vista fue "qué? un singleton Serializable?" mmmm un singleton no puede ser Serializable, y un objeto que implementa Serializable no puede ser un singleton.

En caso que las razones no sean obvias: suponte que tienes tu Singleton, sólo existe una instancia de tu clase en el server. Pero al serializarlo, estás enviando una copia a otro lugar; al llegar a su destino cuando lo deserialicen tendrán una instancia nueva de una clase que se supone que debe ser un singleton. No importa que el constructor sea privado, esto lo puedes hacer desde otra clase y se crean nuevas instancias. Por ejemplo:

 

ezamudio..

la idea no era enviar el singleton como tal
 

actualmente evio y recibo trama es un String de tamaño variable con una parte fija (encabezado) y una parte de datos que puede ser variable
las trama que manejo tienen las siguientes estructura ejemplo 005412500000078456987PC0000007411| dato1,dato2,dato3|
los primeros 4 bytes tamaño de la trama 0054
los siguientes 3 bytes tamaño es el codigo de transaccion 125 (segun este codigo ejecuto un paquete en oracle)
los siguientes dos bytes 00 es el estado de la transaccion 00 todo ok
los siguientes 12 bytes 000078456987 id de usuario
los siguientes 12 bytes PC0000007411 maquina de usuario

lo que esta en | dato1,dato2,dato3| son los datos variables

cuando envio una de esta tramas al server y el server me responde el encabezado debe ser el mismo lo unico que vario es la parde de datos
hago un minimo de comprobaciones que el tamaño de la trama coincida con los primeros 4 bytes y que dicha trama me pertenece juntando
la parte idusuario y host si la trama que recibo tiene mi id junto con mi host la trama es mia sino la desecho esta comprobacion la empeze hacer por que una vez me paso que algunas ocaciones las tramas se me mezclaba en no se que punto y me llegaban trama que no le pertenecian a otro usuario no supe si el error era del listener o de la base de datos del programa cliente (JAVA WEB START aprox 1500 usuarios concurrentes).

el singlenton era para manejar la conexion y el evio de datos al server y el input y output me los manejara el singleton
 

y en otra clase hacaer algo como

 

y mi singleton sendDTo tiene tanto mi input como mi ouput y los tengo como de una manera global que puedo usar donde lo necesite
algo asi era mi idea y para lo que realmente queria usar el singleton.

Imagen de echan

hey hackchan usar variables

hey hackchan usar variables globales en un entorno concurrente es la peor idea que puedes tener, nada impide que mas de un hilo modifique el estado compartido y empieces a ver inconsistencias.

Podrias para controlar el acceso usando bloqueo.

Otra manera mediante estructuras concurrentes como un ConcurrentMap o una BlockingQueue.

Imagen de Cid

Perdón por abrir de nuevo

Perdón por abrir de nuevo esta discusión, pero tengo una duda mencionan en este y un post más reciente acerca del patron Singletón y los objetos Serializables son mutuamente excluyentes porque la serialización es contranatura al patrón que sirve para genera una instancia única y no más de un objeto, pero bueno he visto que este vínculo si realiza un singleton con el siguiente fragmento de código:

 

Dice ahí que si agrego este método devolverá el mismo hashCode pero lo que estoy invocando es un atributo de Clase y jamás se serializó verdad ?, mmm pero me surge una pregunta ¿ Un atributo de clase se carga cada vez que se carga la clase, entonces si lo cargo en diferentes JVM sigue siendo singleton ? lo que leí es que readResolve es utilizado en lugar del metodo readObject de la clase InputStream que debó de sobre escribir para que lo utilice en lugar de readObject y así lea la misma intancia en lugar de que generé una nueva.

 

Al final entonces no se serializa nada o sí ?

Imagen de ezamudio

jvms

Obvio tiene que ser un objeto distinto en distintas jvms. Son distintos procesos, no te va a dar un proxy automágicamente al objeto de la primera jvm donde se encuentra.

La idea del singleton es que solamente exista UNA instancia en toda la jvm que está corriendo.

Si sobreescribes   entonces efectivamente utilizas la instancia existente del singleton en vez de deserializar la que viene del stream. Sí se serializa el objeto, pero no se usa.

Por qué no ponemos fin de una vez a todo esto de los singletons serializables, no con discusiones, sino con PRUEBAS?

 

Imagen de Cid

Gracias duda resuelta

Gracias duda resuelta y eso del proxy automágico se podría hacer con RMI ? jajaja mejor ahi le paro ya son muchos escenarios jajajaja. Gracias.

Imagen de ezamudio

RMI

RMI usa la misma serialización que estoy usando en mi ejemplo para pasar parámetros y resultados, por lo que si devuelves un singleton como resultado de una llamada RMI o lo pasas como parámetro, entonces sí debes hacer lo de