Preguntas de entrevista multihilo (2020)

Multithreading
1. ¿Cuál es la diferencia entre paralelo y concurrente?
Paralelo: se ejecutan varias tareas en el mismo núcleo de la CPU por turnos (alternativamente) en segmentos de tiempo subdivididos. Lógicamente, esas tareas se ejecutan simultáneamente.
Simultaneidad: múltiples procesadores o procesadores de múltiples núcleos procesan múltiples tareas simultáneamente.
Como se muestra a continuación:
concurrente y paralelo concurrente = dos colas y una máquina de café. Paralelo = dos colas y dos cafeteras.

2. ¿La diferencia entre hilos y procesos?
Hay al menos un proceso en un programa, al menos un subproceso en un proceso y múltiples subprocesos en un proceso para aumentar la velocidad de ejecución del programa.

3. ¿Qué es un hilo de demonio?
Un hilo de daemon es un proceso especial que se ejecuta en segundo plano. Es independiente del terminal de control y realiza periódicamente ciertas tareas o espera a que ocurran ciertos eventos. En Java, el subproceso de recogida de basura es un subproceso especial de daemon.

4. ¿Cuáles son las formas de crear hilos?
Hay tres formas de crear subprocesos: heredar el método de ejecución de subprocesos; implementar la interfaz Runnable; implementar la interfaz invocable.

5. ¿Cuál es la diferencia entre ejecutable y invocable?
runnable no tiene valor de retorno, invocable puede obtener un valor de retorno y invocable puede verse como un suplemento de ejecutable.

6. ¿Cuál es el estado del hilo?
El estado del subproceso: NUEVO no se ha iniciado
RUNNABLE se está ejecutando BLOQUEADO bloqueado (bloqueo sincronizado o bloqueo de E / S bloqueado) ESPERA estado de espera permanente TIMED_WAITING espera el tiempo especificado para volver a despertarse estado TERMINADO ejecución completada

7. ¿Cuál es la diferencia entre sleep () y wait ()?
Diferentes clases: sleep () proviene de Thread, wait () proviene de Object. Libere el bloqueo: sleep () no libera el bloqueo; wait () libera el bloqueo. El uso es diferente: sleep () se recuperará automáticamente cuando se acabe el tiempo; wait () se puede despertar directamente usando notify () / notifyAll ().

8. ¿Cuál es la diferencia entre notify () y notifyAll ()?
notifyAll () activará todos los subprocesos, notify () activará un subproceso.
Después de llamar a notifyAll (), todos los hilos se moverán del grupo de espera al grupo de bloqueo y luego participarán en la competencia del bloqueo. Si la competencia es exitosa, continuará ejecutándose. Si no es exitoso, permanecerá en el grupo de bloqueo y esperará a que se libere el bloqueo.
Notify () solo activará un subproceso, que es controlado específicamente por la máquina virtual.

9. ¿Cuál es la diferencia entre el hilo run () y start ()?
El método start () se usa para iniciar el hilo, y el método run () se usa para ejecutar el código de tiempo de ejecución del hilo. run () se puede llamar repetidamente, pero start () solo se puede llamar una vez.

10. ¿Cuáles son las diversas formas de crear un grupo de subprocesos?
Hay siete formas de crear un grupo de subprocesos, el núcleo es el último:
newSingleThreadExecutor (): se caracteriza por que el número de subprocesos de trabajo está limitado a 1, operando una cola de trabajo ***, por lo que garantiza que todas las tareas sean Al ejecutarse secuencialmente, como máximo una tarea estará activa, y el usuario no puede cambiar la instancia del grupo de subprocesos, por lo que puede evitar cambiar el número de subprocesos;
newCachedThreadPool (): es un grupo de subprocesos utilizado para procesar una gran cantidad de tareas de trabajo de corto tiempo , Tiene varias características distintivas: intentará almacenar en caché los subprocesos y reutilizarlos, cuando no haya un subproceso de caché disponible, creará un nuevo subproceso de trabajo; si el subproceso está inactivo durante más de 60 segundos, se terminará y se moverá del caché; cuando esté inactivo durante mucho tiempo Este tipo de grupo de subprocesos no consumirá ningún recurso. SynchronousQueue se usa internamente como una cola de trabajo; newFixedThreadPool (int nThreads): reutiliza un número específico de subprocesos (nThreads), detrás del cual se encuentra el uso de *** cola de trabajo, en cualquier momento, como máximo, los subprocesos de trabajo nThreads están activos. Esto significa que si el número de tareas excede el número de colas activas, esperará a que aparezcan subprocesos inactivos en la cola de trabajo; si sale un subproceso de trabajo, se creará un nuevo subproceso de trabajo para completar el número especificado de nThreads;
newSingleThreadScheduledExecutor (): Cree un grupo de subprocesos simples y regrese a ScheduledExecutorService para la programación de trabajo programada o periódica;
newScheduledThreadPool (int corePoolSize): similar a newSingleThreadScheduledExecutor (), crea un servicio ScheduledExecutorService, que puede realizar una programación de trabajo programada o periódica, la diferencia es si se trata de un solo subproceso de trabajo o varios subprocesos de trabajo; newWorkStealingPool (paralelismo int): esto es frecuente Ignore el grupo de subprocesos, Java 8 solo agregó este método de creación, construirá ForkJoinPool internamente, usará el algoritmo Work-Stealing para procesar tareas en paralelo y no garantizará el orden de procesamiento;
ThreadPoolExecutor (): es la creación del grupo de subprocesos más original, por encima de 1- 3 Los métodos de creación son todos encapsulados de ThreadPoolExecutor.

11. ¿Cuáles son los estados del grupo de subprocesos?
EN EJECUCIÓN: este es el estado más normal, acepta nuevas tareas y procesa tareas en la cola de espera.
APAGADO: no acepte nuevos envíos de tareas, pero continuará procesando tareas en la cola de espera.
STOP: no acepte nuevos envíos de tareas, ya no procese tareas en la cola de espera e interrumpa el hilo que está ejecutando la tarea.
TIDYING: todas las tareas se destruyen, workCount es 0 y el estado del grupo de subprocesos se cambia a TIDYING, se ejecuta el método de enlace terminado ().
TERMINADO: una vez que finaliza el método terminado (), el estado del grupo de subprocesos se convierte en esto. ¿Cuál es la diferencia entre los métodos submit () y execute () en el grupo de subprocesos? execute (): solo puede ejecutar tareas Runnable.
submit (): puede ejecutar tareas ejecutables y invocables.
Las tareas invocables pueden obtener el valor de retorno de ejecución, mientras que la ejecución Runnable no tiene valor de retorno.
12. ¿Cómo garantizar la seguridad de la operación multihilo en los programas Java?
Método 1: utilice clases de seguridad, como las clases en Java. Util. Concurrent.
Método dos: use el bloqueo automático sincronizado.
Método 3: use el bloqueo manual. El código Java para el bloqueo manual es el siguiente: Bloqueo de bloqueo = nuevo ReentrantLock (); bloqueo. Bloqueo (); intente {Sistema. Salida. Println ("Adquirir bloqueo");} captura (Excepción e) {// TODO: manejar excepción} finalmente {Sistema. Fuera. Println ("Liberar bloqueo"); bloquear. Desbloquear ();
}

  1. ¿Cuál es el principio de la escalada de bloqueo sincronizado en subprocesos múltiples?
    El principio de la actualización de bloqueo sincronizado: hay un campo threadid en el encabezado del objeto del objeto de bloqueo. El threadid está vacío cuando se accede por primera vez. El jvm le permite mantener el bloqueo sesgado y establece el threadid en su threadid. Cuando ingrese nuevamente, lo hará Primero determine si el threadid es consistente con su id. De hilo. Si es consistente, puede usar este objeto directamente. Si no es consistente, el bloqueo de sesgo de actualización es un bloqueo liviano. El bloqueo se obtiene a través de un cierto número de ciclos de centrifugado. Después de un cierto número de ejecuciones, si no es normal Después de obtener el objeto que se utilizará, la cerradura se actualizará de una cerradura ligera a una pesada. Este proceso constituye la actualización de una cerradura sincronizada. El propósito de la actualización del bloqueo: la actualización del bloqueo es reducir el consumo de rendimiento causado por el bloqueo. La implementación optimizada de sincronizado después de Java 6 utiliza una actualización de bloqueo sesgada a un bloqueo ligero y luego a un bloqueo pesado, lo que reduce el costo de rendimiento de los bloqueos.
    14. ¿Qué es un punto muerto?
    Cuando el hilo A tiene el bloqueo exclusivo a, e intenta adquirir el bloqueo exclusivo b, mientras que el hilo B tiene el bloqueo exclusivo b, e intenta adquirir el bloqueo exclusivo a, sucederá que dos hilos AB se necesitan entre sí. El fenómeno de bloqueo que ocurre, lo llamamos punto muerto.
    15. ¿Cómo prevenir el punto muerto?
    Intente utilizar el método tryLock (tiempo de espera prolongado, unidad TimeUnit) (ReentrantLock, ReentrantReadWriteLock), establezca el período de tiempo de espera, el tiempo de espera puede salir para evitar el punto muerto. Intente utilizar Java. Util. Clase concurrente concurrente en lugar de su propio bloqueo de escritura a mano. Intente reducir la granularidad del bloqueo, intente no usar el mismo bloqueo para varias funciones. Minimice el número de bloques de código sincronizado.
    16. ¿Qué es ThreadLocal? ¿Cuáles son los escenarios de uso?
    ThreadLocal proporciona copias independientes de variables para cada hilo que usa la variable, por lo que cada hilo puede cambiar independientemente su propia copia sin afectar las copias correspondientes a otros hilos. Los escenarios de uso clásicos de ThreadLocal son la conexión a la base de datos y la administración de sesiones.
    17. ¿Cuál es el principio de implementación subyacente de sincronizado?
    Synchronized se implementa mediante un par de instrucciones monitornter / monitorexit, y el objeto monitor es la unidad básica de sincronización. Antes de Java 6, la implementación del monitor dependía completamente del mutex dentro del sistema operativo. Debido a que el modo de usuario al modo kernel debe cambiarse, la operación de sincronización es una operación pesada sin diferencia, y el rendimiento también es muy bajo. Pero cuando Java 6, la máquina virtual Java llevó a cabo un gran
    cuchillo de mejora hacha amplia, proporciona tres aplicación monitor diferente, que se dice a menudo que los tres cerraduras diferentes: Bloqueo sesgada (con prioridad de bloqueo), de peso ligero Las cerraduras de grado y las cerraduras de peso pesado han mejorado enormemente su rendimiento.
    18. ¿Cuál es la diferencia entre sincronizado y volátil?
    volatile es un modificador variable; sincronizado es una clase, método y segmento de código modificado. Volátil solo puede lograr la visibilidad modificada de las variables, y no puede garantizar la atomicidad; mientras que sincronizado puede garantizar la visibilidad modificada y la atomicidad de las variables. volátil no causa bloqueo de hilo; sincronizado puede causar bloqueo de hilo.
    19. ¿Cuál es la diferencia entre sincronizado y bloqueo?
    sincronizado puede bloquear clases, métodos y bloques de código; el bloqueo solo puede bloquear bloques de código. Sincronizado no necesita adquirir y liberar bloqueos manualmente. Es fácil de usar. Si ocurre una excepción, liberará automáticamente el bloqueo y no provocará un punto muerto; mientras que los bloqueos deben agregar y liberar bloqueos ellos mismos. Si no se usa el desbloqueo () para liberar el bloqueo, causará la muerte. Cerradura A través del bloqueo, puede saber si ha obtenido el bloqueo con éxito, pero sincronizado no puede hacerlo. 20. ¿Cuál es la diferencia entre sincronizado y ReentrantLock?
    La implementación temprana de sincronizado es relativamente ineficiente. En comparación con ReentrantLock, el rendimiento de la mayoría de los escenarios es bastante diferente, pero en Java 6 la sincronización sincronizada se ha mejorado mucho. Las principales diferencias son las siguientes: ReentrantLock es más flexible de usar, pero debe cooperar con la acción de liberar el bloqueo; ReentrantLock debe adquirir y liberar el bloqueo manualmente, y sincronizado no requiere liberación manual y desbloqueo del bloqueo; ReentrantLock solo es aplicable a bloqueos de bloque de código, y sincronizado se puede usar para modificar Métodos, bloques de código, etc. Las variables marcadas con volátil no son optimizadas por el compilador; las variables marcadas con sincronizado pueden ser optimizadas por el compilador.
  2. ¿Cuéntame sobre el principio de atómica?
    atomic utiliza principalmente CAS (Compare And Wwap) y métodos volátiles y nativos para garantizar operaciones atómicas, evitando así la alta sobrecarga de sincronizado y mejorando en gran medida la eficiencia de ejecución.

Supongo que te gusta

Origin blog.51cto.com/14760318/2486660
Recomendado
Clasificación