Red de conocimiento informático - Aprendizaje de programación - Desarrollo de máximo rendimiento y prevención de riesgos de grupos de subprocesos en programación Java

Desarrollo de máximo rendimiento y prevención de riesgos de grupos de subprocesos en programación Java

Aunque el grupo de subprocesos puede mejorar en gran medida el rendimiento de concurrencia del servidor, existen ciertos riesgos al usarlo. Como todas las aplicaciones multiproceso, las aplicaciones creadas con grupos de subprocesos son propensas a sufrir diversos problemas de concurrencia, como contiendas por recursos compartidos y bloqueos. Además, si la implementación del grupo de subprocesos en sí no es sólida, o el grupo de subprocesos no se usa de manera racional, puede provocar fácilmente bloqueos relacionados con el grupo de subprocesos, recursos insuficientes del sistema y fugas de subprocesos.

1. Punto muerto

Cualquier aplicación multiproceso tiene el riesgo de sufrir un punto muerto. La situación más simple que causa un punto muerto es que el hilo A mantiene el bloqueo del objeto X y está esperando el bloqueo del objeto Y, mientras que el hilo B mantiene el bloqueo del objeto Y y está esperando el bloqueo del objeto X. Ni el subproceso A ni el subproceso B liberan el bloqueo que mantienen y esperan el bloqueo de la otra parte. Esto hace que los dos subprocesos esperen para siempre y se produzca un punto muerto.

Aunque cualquier programa multiproceso tiene el riesgo de bloquearse, los grupos de subprocesos también pueden causar otro tipo de bloqueo. En este caso, se supone que todos los subprocesos de trabajo en el grupo de subprocesos están bloqueados mientras ejecutan sus respectivas tareas y todos están esperando el resultado de la ejecución de una determinada tarea A. La tarea A todavía está en la cola de trabajos. Como no hay ningún subproceso inactivo, la tarea A no se puede ejecutar. Esto hace que todos los subprocesos de trabajo en el grupo de subprocesos se bloqueen para siempre y se produzca un punto muerto.

2. Recursos del sistema insuficientes

Si el número de subprocesos en el grupo de subprocesos es muy grande, estos subprocesos consumirán una gran cantidad de recursos, incluida la memoria y otros recursos del sistema, lo que es grave. afectando el rendimiento del sistema.

3. Errores de concurrencia

La cola de trabajo del grupo de subprocesos se basa en los métodos wait() y notify() para permitir que el subproceso de trabajo obtenga tareas a tiempo, pero ambos métodos son difíciles. para usar. Si no se codifican correctamente, las notificaciones se pueden perder, lo que hace que los subprocesos de trabajo permanezcan inactivos e ignoren las tareas en la cola de trabajos que deben procesarse. Por lo tanto, se debe tener mucho cuidado al utilizar estos métodos, ya que incluso los expertos pueden cometer errores en este ámbito. Es mejor utilizar un grupo de subprocesos existente y más maduro. Por ejemplo, utilice directamente la clase de grupo de subprocesos en el paquete java.util.concurrent.

4. Fuga de subprocesos

Un riesgo grave al utilizar un grupo de subprocesos es la fuga de subprocesos. Para un grupo de subprocesos con un número fijo de subprocesos de trabajo, si un subproceso de trabajo genera una RuntimeException o un error al ejecutar una tarea, y estas excepciones o errores no se detectan, el subproceso de trabajo terminará de manera anormal, lo que provocará que el grupo de subprocesos pierda permanentemente un hilo de trabajo. Si todos los subprocesos de trabajo terminan de forma anormal, el grupo de subprocesos finalmente se vacía y no hay subprocesos de trabajo disponibles para manejar las tareas.

Otra situación que causa fugas de subprocesos es que el subproceso de trabajo se bloquea mientras realiza una tarea, como esperar a que el usuario ingrese datos, pero el usuario no ha ingresado datos (tal vez porque el usuario se fue). , lo que hace que este hilo de trabajo esté bloqueado todo el tiempo. Un subproceso de trabajo de este tipo existe sólo de nombre y, en realidad, no realiza ninguna tarea. Si todos los subprocesos de trabajo en el grupo de subprocesos están en dicho estado bloqueado, entonces el grupo de subprocesos no podrá procesar las tareas recién agregadas. [siguiente página]

5. Sobrecarga de tareas

Cuando hay una gran cantidad de tareas esperando a ser ejecutadas en la cola de trabajo, estas tareas en sí mismas pueden consumir demasiados recursos del sistema y causar un escasez de recursos del sistema.

En resumen, los grupos de subprocesos pueden conllevar varios riesgos. Para evitarlos tanto como sea posible, debe seguir los siguientes principios al utilizar grupos de subprocesos.

(1) Si la tarea A necesita esperar sincrónicamente el resultado de la ejecución de la tarea B durante la ejecución, entonces la tarea A no es adecuada para agregarse a la cola de trabajo del grupo de subprocesos. Si una tarea como la tarea A, que necesita esperar los resultados de ejecución de otras tareas, se agrega a la cola de trabajo, puede causar un punto muerto en el grupo de subprocesos.

(2) Si una determinada tarea puede estar bloqueada durante mucho tiempo, se debe establecer un tiempo de espera para evitar que el hilo de trabajo se bloquee permanentemente y provoque fugas de hilo.

En el programa del servidor, cuando un hilo está esperando una conexión de cliente o esperando datos enviados por el cliente, puede bloquearse. El tiempo de espera se puede configurar de las siguientes maneras:

Llame al método setSoTimeout (int timeout) de ServerSocket para establecer el tiempo de espera para las conexiones del cliente;

Para cada socket conectado al client, llame al método setSoTimeout (int timeout) del Socket para establecer el tiempo de espera para que el cliente envíe datos.

(3) Comprenda las características de la tarea y analice si la tarea realiza operaciones de E / S que a menudo se bloquean o realiza operaciones informáticas que nunca se bloquean. El primero ocupa la CPU de forma intermitente, mientras que el segundo tiene una mayor utilización de la CPU. ¿Cuánto tiempo se estima que tomará completar la tarea? ¿Es una misión a corto plazo o una misión a largo plazo?

Clasifique las tareas según las características de las tareas y luego agregue diferentes tipos de tareas a las colas de trabajo de diferentes grupos de subprocesos, de modo que cada grupo de subprocesos se pueda ajustar por separado según las características de las tareas.

(4) Ajusta el tamaño del grupo de subprocesos. El tamaño óptimo del grupo de subprocesos depende principalmente de la cantidad de CPU disponibles en el sistema y las características de las tareas en la cola de trabajos. Si solo hay una cola de trabajo en un sistema con N CPU y todas son tareas computacionales (sin bloqueo), entonces la utilización máxima de la CPU generalmente se obtendrá cuando el grupo de subprocesos tenga N o N 1 subprocesos de trabajo.

Si la cola de trabajo contiene tareas que realizan operaciones de E/S y a menudo se bloquean, el tamaño del grupo de subprocesos debe exceder la cantidad de CPU disponibles, porque no todos los subprocesos de trabajo están trabajando todo el tiempo. Seleccione una tarea típica y luego estime la relación WT/ST entre el tiempo de espera (WT) y el tiempo real ocupado por la CPU para los cálculos (ST) durante la ejecución de esta tarea. Para un sistema con N CPU, se deben configurar aproximadamente N×(1 WT/ST) subprocesos para garantizar que las CPU se utilicen por completo.

Por supuesto, la utilización de la CPU no es lo único que se debe considerar al ajustar el tamaño del grupo de subprocesos. A medida que aumenta la cantidad de subprocesos de trabajo en el grupo de subprocesos, también encontrará limitaciones en la memoria u otros recursos del sistema, como la cantidad de sockets, identificadores de archivos abiertos o conexiones de bases de datos. Es necesario garantizar que los recursos del sistema consumidos por subprocesos múltiples estén dentro del rango de carga del sistema.

(5) Evitar la sobrecarga de tareas. El servidor debe limitar la cantidad de conexiones de clientes simultáneas según la capacidad de carga del sistema. Cuando el número de conexiones de clientes simultáneas excede el límite, el servidor puede rechazar la solicitud de conexión e informar amigablemente al cliente: el servidor está ocupado, inténtelo nuevamente más tarde.