ventana una sencillo para juegos hechos hacer ejemplos crear como codigo bienvenida java multithreading synchronization thread-priority

una - ¿Cómo se puede asegurar en Java que un bloque de código no puede ser interrumpido por ningún otro hilo?



jframe netbeans codigo (10)

Usar el enfoque sincronizado (en los diversos formularios publicados aquí) no ayuda en absoluto.

Ese enfoque solo ayuda a asegurar que un hilo ejecuta la sección crítica a la vez , pero esto no es lo que desea. Debe evitar que el hilo sea interrumpido.

El bloqueo de lectura / escritura parece ayudar, pero no hace ninguna diferencia ya que ningún otro hilo está intentando usar el bloqueo de escritura.

Solo hace que la aplicación sea un poco más lenta porque la JVM debe realizar validaciones adicionales para ejecutar la sección sincronizada (utilizada solo por un hilo, por lo tanto, un desperdicio de CPU)

En realidad, en la forma en que lo tienes, el hilo no está " realmente " siendo interrumpido. Pero parece que sí, porque tiene que ceder el tiempo de CPU a otros hilos. La forma en que funcionan los hilos es; la CPU le da a cada hilo la oportunidad de correr por un tiempo durante cortos periodos de tiempo. Incluso cuando se ejecuta un solo subproceso, ese subproceso está generando tiempo de CPU con otros subprocesos de otras aplicaciones (suponiendo que una sola máquina de procesador mantenga la discusión simple).

Esa es probablemente la razón por la que le parece que el hilo se está pausando / interrumpiendo de vez en cuando, ya que el sistema permite que cada hilo de la aplicación se ejecute durante un tiempo.

¿Entonces que puedes hacer?

Para aumentar la percepción de que no hay interrupciones, una cosa que puede hacer es asignarle una prioridad más alta a su hilo y disminuirlo para el resto.

Si todos los hilos tienen la misma prioridad, un posible programa de hilos 1,2,3 podría ser así:

Distribuidos equitativamente

1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3

Mientras configura max para 1 y min para 2,3, podría ser así:

Más CPU para el hilo 1

1,1,1,2,1,1,3,1,1,1,2,1,1,1,3,1,2,1,1,1

Para que un subproceso sea interrumpido por otro subproceso, tiene que estar en un estado de interrupción, que se consigue llamando, Object.wait, Thread.join o Thread.sleep

Debajo de un código divertido para experimentar.

Código 1: prueba cómo cambiar la prioridad de los hilos. Vea los patrones en la salida.

public class Test { public static void main( String [] args ) throws InterruptedException { Thread one = new Thread(){ public void run(){ while ( true ) { System.out.println("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"); } } }; Thread two = new Thread(){ public void run(){ while ( true ) { System.out.println("............................................."); } } }; Thread three = new Thread(){ public void run(){ while ( true ) { System.out.println("------------------------------------------"); } } }; // Try uncommenting this one by one and see the difference. //one.setPriority( Thread.MAX_PRIORITY ); //two.setPriority( Thread.MIN_PRIORITY ); //three.setPriority( Thread.MIN_PRIORITY ); one.start(); two.start(); three.start(); // The code below makes no difference // because "one" is not interruptable Thread.sleep( 10000 ); // This is the "main" thread, letting the others thread run for aprox 10 secs. one.interrupt(); // Nice try though. } }

Código 2. Muestra de cómo se puede interrumpir realmente un hilo (mientras duerme en este caso)

public class X{ public static void main( String [] args ) throws InterruptedException { Thread a = new Thread(){ public void run(){ int i = 1 ; while ( true ){ if ( i++ % 100 == 0 ) try { System.out.println("Sleeping..."); Thread.sleep(500); } catch ( InterruptedException ie ) { System.out.println( "I was interrpted from my sleep. We all shall die!! " ); System.exit(0); } System.out.print("E,"); } } }; a.start(); Thread.sleep( 3000 ); // Main thread letting run "a" for 3 secs. a.interrupt(); // It will succeed only if the thread is in an interruptable state } }

ejempl

new Thread(new Runnable() { public void run() { while(condition) { *code that must not be interrupted* *some more code* } } }).start(); SomeOtherThread.start(); YetAntherThread.start();

¿Cómo puede asegurarse de que el código que no se debe interrumpir no se interrumpa?


Antes de que se interrumpa un hilo, se llama al método checkAccess () del administrador de seguridad. Implemente su propio administrador de seguridad, llame a System.setSecurityManager para instalarlo y asegúrese de que no permita que ningún otro hilo lo interrumpa mientras se encuentre en la sección crítica.


En realidad, puede hacer esto si controla la instancia de la secuencia en la que se está ejecutando. Obviamente, hay un montón de advertencias sobre esto (como colgar operaciones io), pero esencialmente se puede subprocesar Subproceso y anular el método de interrupción (). luego puede poner algún tipo de booleano en su lugar de manera que cuando active un indicador, las llamadas de interrupción () a su hilo sean ignoradas o mejor aún almacenadas para más adelante.


La mejor solución a medio camino sería sincronizar todos los hilos en algún objeto común para que no se puedan ejecutar otros hilos mientras se encuentre en la sección crítica.

Aparte de eso, no creo que sea posible. ¿Y tengo curiosidad sobre qué tipo de problema requiere este tipo de solución?


No se puede, al menos no con Java normal, ejecutándose en un sistema operativo normal en tiempo no real. Incluso si otros hilos no interrumpen el suyo, otros procesos podrían hacerlo. Básicamente, no podrá garantizar que obtendrá una CPU para usted solo hasta que haya terminado. Si desea este tipo de garantía, debe usar algo como Java Real-Time System. No sé lo suficiente para saber si eso definitivamente proporcionaría la instalación que desea.

Lo mejor que puedes hacer es evitar ese requisito en primer lugar.


Realmente necesitas dejar más información.

No puede detener la ejecución de otros procesos del sistema a menos que ejecute un sistema operativo en tiempo real. ¿Es eso lo que quieres decir?

No puede detener la recolección de basura, etc. a menos que ejecute un java en tiempo real. ¿Es eso lo que querías?

Lo único que queda es: si simplemente quieres que todos tus otros hilos Java no se interrumpan porque todos tienden a acceder a algún recurso sin control, lo estás haciendo mal. Diseñarlo correctamente para que los objetos / datos a los que NECESITA tener acceso de manera sincronizada estén sincronizados, entonces no se preocupe porque otros hilos lo interrumpan porque sus objetos sincronizados están seguros.

¿Perdí algún posible caso?


Suponiendo que solo le preocupa la contención de hilos a nivel de aplicación y suponiendo que está dispuesto a preocuparse por los bloqueos como sugieren otros (lo cual, en mi humilde opinión, es una mala idea ), debería usar ReadWriteLock y no una simple sincronización de objetos:

import java.java.util.concurrent.locks.*; // create a fair read/write lock final ReadWriteLock rwLock = new ReentrantReadWriteLock(true); // the main thread grabs the write lock to exclude other threads final Lock writeLock = rwLock.writeLock(); // All other threads hold the read lock whenever they do // *anything* to make sure the writer is exclusive when // it is running. NOTE: the other threads must also // occasionally *drop* the lock so the writer has a chance // to run! final Lock readLock = rwLock.readLock(); new Thread(new Runnable() { public void run() { while(condition) { writeLock.lock(); try { *code that must not be interrupted* } finally { writeLock.unlock(); } *some more code* } } }).start(); new SomeOtherThread(readLock).start(); new YetAntherThread(readLock).start();


El procesamiento de errores es un ejemplo de un caso de uso en el que es muy útil para evitar que los hilos se interrumpan. Supongamos que tiene un gran servidor de subprocesos múltiples y surge una condición externa que provoca la detección de errores en varios subprocesos de trabajo simultáneamente. Cada subproceso de trabajo genera una notificación de que se produjo un error. Digamos además que la respuesta deseada es llevar el servidor a un estado seguro que le permita reiniciarse después de que se borre la condición de error.

Una forma de implementar este comportamiento es tener una máquina de estado para el servidor que procesa cambios de estado en orden total. Una vez que llega una notificación de error, la coloca en la máquina de estado y deja que la máquina de estado la procese en su totalidad sin interrupción. Aquí es donde desea evitar interrupciones: desea la primera notificación para que se ejecute el controlador de errores. Las notificaciones adicionales no deberían interrumpirlo o reiniciarlo. Esto suena fácil pero realmente no lo es, supongamos que la máquina de estado pusiera el servidor en línea. Desearía interrumpir eso para permitir el procesamiento de errores en su lugar. Entonces algunas cosas son interrumpibles pero otras no.

Si interrumpe el hilo de procesamiento de errores, puede expulsar al controlador de errores fuera del agua durante el procesamiento del método sincronizado, dejando los objetos en un estado potencialmente sucio. Este es el quid del problema: las interrupciones de hilo van alrededor del mecanismo de sincronización normal en Java.

Esta situación es rara en aplicaciones normales. Sin embargo, cuando surge, el resultado puede ser fallas bizantinas que son muy difíciles de anticipar y mucho menos curar. La respuesta es proteger tales secciones críticas de las interrupciones.

Por lo que puedo decir, Java no te da un mecanismo para evitar que un hilo sea interrumpido. Incluso si lo hiciera, probablemente no desee utilizarlo porque la interrupción podría ocurrir fácilmente en bibliotecas de bajo nivel (por ejemplo, procesamiento de socket TCP / IP) donde el efecto de apagar interrupciones puede ser muy impredecible.

En cambio, parece que la mejor manera de manejar esto es diseñar su aplicación de tal manera que tales interrupciones no ocurran. Soy el autor de un pequeño paquete de máquina de estado llamado Tungsten FSM ( https://code.google.com/p/tungsten-fsm ). FSM implementa una máquina simple de estado finito que asegura que los eventos se procesen en orden total. Actualmente estoy trabajando en una corrección de errores que aborda exactamente el problema descrito aquí. FSM ofrecerá una forma de abordar este problema, pero hay muchos otros. Sospecho que la mayoría de ellos involucran algún tipo de máquina de estados y / o cola de eventos.

Si adopta el enfoque de evitar interrupciones, por supuesto crea otro problema si los hilos no interrumpibles se bloquean por alguna razón. En ese punto simplemente estás atascado y tienes que reiniciar el proceso. No parece tan diferente de un punto muerto entre los hilos de Java, que de hecho es una forma en que los hilos no interrumpibles pueden bloquearse. Realmente no hay almuerzo gratis sobre este tipo de problemas en Java.

He pasado mucho tiempo mirando problemas como este: son muy difíciles de diagnosticar y mucho menos resolver. Java realmente no maneja muy bien este tipo de problema de simultaneidad. Sería genial escuchar acerca de mejores enfoques.


Simplemente inicie su propio sub thread, y asegúrese de que las llamadas de interrupción nunca se filtren a él.

new Thread(new Runnable() { public void run() { Thread t = new Thread() { public void run() { *code that must not be interrupted* } } t.start(); //Nothing else holds a reference to t, so nothing call call interrupt() on it, except for your own code inside t, or malicious code that gets a list of every live thread and interrupts it. while( t.isAlive() ) { try { t.join(); } catch( InterruptedException e ) { //Nope, I''m busy. } } *some more code* } } }).start(); SomeOtherThread.start(); YetAntherThread.start();


Creo que debes bloquear una bandera de interrupción. ¿Qué tal algo así (no probado):

new Thread() { boolean[] allowInterrupts = { true }; public void run() { while(condition) { allowInterrupts[0] = false; *code that must not be interrupted* allowInterrupts[0] = true; *some more code* } } public void interrupt() { synchronized (allowInterrupts) { if (allowInterrupts[0]) { super.interrupt(); } } } }.start(); SomeOtherThread.start(); YetAntherThread.start();