Reservación de memoria en java

Hola comunidad, que tal !!! Aquí de nuevo pidiendo de su ayuda...

Quisiera saber si en java existe alguna forma de reservar memoria para datos que recibo via sockets??. o tenerlos en espera en lo que los valido y despues guardarlos.
Lo que pasa es que estoy recibiendo datos por medio de sockets, pero son demasiados (a veces hasta 2000 paquetes por segundos) que despues de un cierto tiempo de recibir, se queda parado sin rcibir nada, y me envia un mensaje de memoria no disponible o algo así...

Cuando recibo datos(bytes), tengo que validar que son los correctos, así que hago algunos proceso antes de guardarlos en un archivo .txt, entonces es cuando supongo que se satura mi memoria porque tarda en liberar cada paquete de bytes...
Ojalá alguien pueda ayudarme con esto....alguna solución...Gracias.

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 ezamudio

thread pool

Tu problema es que haces todo en el mismo hilo: lees un paquete de datos, lo procesas, lees el siguiente paquete de datos, lo procesas, etc. Pero si te tardas mucho en el procesamiento, eventualmente el buffer de lectura del socket se llena y puedes saltarte por completo algunos paquetes o simplemente ya no puedes leer porque de repente te encuentras con paquetes incompletos.

El hilo que lee del socket debería solamente leer cada paquete de datos y encolarlo en un thread pool para su procesamiento por separado. De esa manera ya no importa si el procesamiento es más lento que la lectura (aunque si este ritmo es constante, inevitablemente se te va a terminar la memoria y necesitas entonces hacer algo más escalable).

Un ejemplo muy simple:

 

Y eso de que se te satura la memoria, pasa muy rápido? Cuánta memoria tienes en hardware? Tienes un servidor dedicado a tu aplicación? Asígnale toda la memoria posible a tu aplicación, modificando los parámetros de arranque, normalmente es por ejemplo:   eso sería para que la JVM arranque con 32MB de memoria y pueda crecer hasta 1GB; si tuvieras por ejemplo 8GB de RAM en un servidor dedicado pues podrías fácilmente hacer algo como   pero pues eso ya depende de tu ambiente de producción (esos son parámetros para la JVM obviamente).

Imagen de jtepetate

Tengo 3 GB en RAM

Si, tengo todo en un solo hilo. El hilo que espera la conexión es el mismo que recibe, procesa y demás. Ese debe ser el problema entonces.
No tengo un servidor dedicado, estoy trabajando en una PC normal solo para hacer la aplicación, ya despues sí se va a pasar a un servidor dedicado.

tengo algo así:

 

Como se puede ver, tengo una clase ConexionServidor que recibe en su constructor el número de puerto que el usuario ingresó en la interfaz (en un jframe), luego entonces inicio el hilo que tiene la clase ConectarServidor para escuchar por ese puerto. Cuando tengo un cliente (solo voy a atender a un cliente a la vez, no varios), le solicito que me envie los datos que se han acumulado durante el día (esto es, que me envie los paquetes anteriores a la actual, si es que los hay. Ya que cada cierto tiempo se generan nuevos paquetes, y debo recuperar todas las que se generen en un día. Si no hay acumulados, entonces solo recibo los que se generen a partir de que el cliente se conecte), es por ello que uso el método solicitarRetransmision(), además en caso de que un paquete llegue mal...
Luego llamo el metodo recibeInformacion(), para que recupere los paquetes del socket.

Bueno, eso es lo que hago. Pero creo que no esta bien del todo...porque cuando vuelvo a llamar el método solicitarRetransmision(), desde el método RecibeInformacion() en caso de recibir un paquete erroneo, me marca un error de thread.

Tengo entendido que el hilo que tengo iniciado en la conexión, debe permanecer así para que esté recibiendo los paquetes...o es que debo detenerlo en algún momento??? . Es correcto lo que estoy haciendo en la clase ConectarServidor, al llamar a los métodos solicitarRetransmision() y recibeInformacion() ???...AGRADEZCO TUS RESPUESTAS.

¿Cual es el error? ¿Cuanta

¿Cual es el error? ¿Cuanta memoria tiene tu VM?

Toma la VisualVM ( viene incluida en el jdk de Java ) y revisa como se está comportando tu aplicación. Vuelve a leer el post de Enrique y aplica lo que te está diciendo sobre la memoria: -Xms4096m -Xmx7168m

Imagen de jtepetate

Lo he intentado, pero no queda...

Hola que tal, buen día.

He intentado resolver mi problema en la recepción de paquetes via socket. Hice como me dijeron, pero no me queda.

Traté de crear un hilo para leer los datos del socket, y otro para que haga el proceso de validación de los mismos, es decir ver que sean los paquetes correctos.

Esta es mi clase que hace la conexión:

 

Mi clase que atenderá al cliente que se conecte: (aqui es donde tengo dudas. Yo aquí estoy solicitando la retransmision() en este mismo hilo, y para leer los datos creo uno nuevo.) No sé si esto es correcto, ya que para enviar datos no tengo problemas, puesto que casi no necesito enviar, es decir, no lo uso mucho. Lo que si uso mucho es la de Recibir.

 

Y este es el que leerá los datos del socket:

 

Y finalmente mi clase que procesa los datos:

 

El problema de esto es que al procesar los datos, no me están llegando en el orden secuencial que espero. Ya probé hacerlo sin hilos separados y sí funcion (recibo los paquetes con el número secuencial que espero), pero ya cuando los separé no funciona igual. Debe ser por la forma en que tengo los hilos. Espero que alguien pueda ayudarme. Estoy apenas entendiendo esto de los hilos, y creo que no lo estoy haciendo de la forma correcta.

GRACIAS POR SU AYUDA.

¿Cual es el error?

¿Cual es el error? ¿Cuanta memoria tiene tu VM?

Imagen de ezamudio

hilos

Debe haber un solo hilo leyendo del socket, y un solo hilo escribiendo al socket.

El hilo que lee del socket, lo único que debe hacer es leer los paquetes, ponerlos en buffers de bytes, y encolarlos para que sean procesados en otro hilo (o un thread pool).

El hilo que escribe al socket, debe tomar los datos que va a escribir de una cola, quitarlos y enviarlos.

Imagen de jtepetate

Tengo 16M en la JVM

Bueno, despues de andar buscando la memoria de mi JVM, no la encontré por ninguna parte. Hice esto para obtenerlo, y me resulta que tengo 16M ,espero sea correcto:

 

El error, como dije en el post, es que mientras estoy recibiendo datos por el socket, llega un momento en que ya la aplicacion se queda plasmada, y me envia un error de memoria llena. Algo así: "OutOfMemoryError".

Este error me arroja cuando ya lleva recibiendo los 2300 paquetes, y de ahí se queda...(recibe entre 30 y 50 paquetes por segundos, no más).

Si ejecuto otra aplicacion que hace lo mismo (recibir paquetes) que está hecho en VB 5, lo hace sin ningún problema. Incluso puede recibir hasta 800 paquetes por segundos. Es más rapido que la anterior.

Pudiera ser lo que me dijo ezamudio, lo de implementar hilos separados, para leer y para procesar; sin embargo no he conseguido que funcione bien. Se que el problema está en la organización de los hilos...porque como dije antes, si lo hago todo en un sólo hilo, me funciona perfectamente, solo que se me termina la memoria.

16MB??!!!!

No.

La razón es que tienes muy poca memoria.

SI hubieras leído ( y hecho caso ) a lo que te dijimos antes:

Hubieras ya superado esto.

Agrega más memoria a tu programa y listo eso debería de solucionar todo.

Para ver cuanta memoria tienes, en la carpeta donde esta tu javac existe un programa que se llama VisualVM abrelo y podras ver cuanta memoria tiene tu app.

Para agregar más memoria, tienes que especificar en la linea de comandos -Xmx=1g -Xms=1g o algo así.

Ya te lo habíamos dicho antes, pero no lo hiciste.

mmmhh algo me dice que de todas formas no vas a leer esto...

Este es el ejecutable:

Este es por ejemplo una aplicación que esta usando 50mb de memoria.

Imagen de jtepetate

Ya amplié la memoria de la JVM

Si cambié la memoria de la JVM como me dijeron. De hecho estoy trabajando con Eclipse, y lo hice de esta manera:

Desde el menú : Run / Run configurations / elijo NombreDeMiProyecto / VM arguments (aqui puse los parámetros de mínimo y máximo de memoria).

Y efectivamente funciona, pero se llena de todas maneras...

La ampliase a 16 mb??!! ...

La ampliase a 16 mb??!! ... Mira el VisualVM en profile...

...

o_O

¬¬

Imagen de jtepetate

La puse como -Xmx1024m

La incrementé a 1024, espero que me funcione, si no, ya os diré...

Agradezco mucho el apoyo amigo...