Este artículo estudia principalmente cuestiones relacionadas de hilos de fondo en Java, de la siguiente manera.
Nunca antes había oído hablar de eso que hay hilos de fondo en Java. En términos generales, JVM (Java Virtual Machine) generalmente incluye dos tipos de subprocesos, a saber, el subproceso de usuario y el hilo de fondo. El llamado hilo de demonio se refiere a un hilo que proporciona un servicio común en segundo plano cuando el programa se está ejecutando, y este hilo no es una parte indispensable del programa. Por lo tanto, cuando todos los subprocesos no background terminan, es decir, cuando el usuario terminan, el programa termina. Al mismo tiempo, matará todos los hilos de fondo en el proceso. Por el contrario, siempre y cuando cualquier hilo que no sea de fondo aún se esté ejecutando, el programa no terminará. Es mejor ejecutar main () que un hilo de no retroceder.
Según esta característica, cuando todos los subprocesos de usuario en la salida de la máquina virtual se ejecutan, el hilo de demonio no tiene objetos de servicio, el JVM sale.
Esto se explica en el código fuente JDK.
* Marca este hilo como un hilo {@linklain #ISDAEMON}
* o un hilo de usuario. La máquina virtual Java sale cuando la única
* Los hilos que se ejecutan son todos los hilos de demonio.
1. Condiciones para comenzar un hilo de fondo:
/*El método setDaemon () debe llamarse antes de iniciar el hilo para establecer este hilo como un hilo de fondo. * En este programa, después de ingresar una cadena, el hilo principal dejará de ejecutarse* Entonces no hay un hilo para el usuario que pueda ejecutarse en el programa. Por lo tanto, el hilo de fondo se detendrá * El JVM se detendrá, y los lectores interesados pueden probarlo usted mismo */public class DaemonRunner implements runnable {@Override public void run () {while (true) {para (int i = 0; i <3; i ++) {system.out.println ("demora"+i);}}}} pública void void (string) Daemon = new Thread (new DaemonRunner ()); Daemon.SetDaemon (true); Daemon.start (); Scanner s = New Scanner (System.in); String String = S.Nextline (); Runtime.getRuntime (). AddShutdown (new Thread () {@anular publica Void run () {super.run (); system.out.println ("") {TimeUnit.milliseConds.sleep (50);} Catch (InterruptedException e) {E.PrintStackTrace ();}}});}}2. Todos los hilos iniciados en el hilo de fondo pertenecen al hilo de fondo. Aunque no especifica explícitamente que son hilos de fondo, de hecho son hilos de fondo.
/* Puede determinar si el hilo es un hilo de fondo llamando al método ISDAEMON (). Si es un hilo de fondo, * entonces cualquier hilo que crea se establece automáticamente en el hilo de fondo * En este ejemplo, el hilo de demonio se establece en el modo de fondo y luego deriva muchos hilos infantiles. Estos hilos no están configurados en el modo de fondo *, pero de hecho son hilos de fondo. Then, the Daemon thread enters an infinite loop and calls the yield method in the loop* to hand over the control to other threads or processes*/class Daemon implements Runnable{private Thread[] t = new Thread[10];@Override public void run() {for (int i = 0; i < t.length; i++) {t[i] = new Thread(new Daemonspawn ()); t [i] .start (); system.out.println ("daemonspawn" + i + "iniciado");} para (int i = 0; i <t.length; i ++) {system.out.println ("t [" + i + "] .isdaemon" + t [i] .isdaemon ()); {Thread.yield ();}}}} Daemonspawn implementa runnable {@Override public void run () {while (true) {thread.yield ();}} public class Daemon Daemon ()); d.setdaemon (true); d.start (); system.out.println ("d.isdaemon () =" + d.isdaemon ()); intente {timeunit.seconds.sleep (1); // deja que el hilo en el fondo de inicio obtenga un cierto tiempo de ejecución. } Catch (InterruptedException e) {E.PrintStackTrace ();}}}Los resultados de la ejecución final son los siguientes:
d.isdaemon () = verdadero
Daémonspawn 0
Daémonspawn primero
Daémonspawn 2sstarted
Daémonspawn 3ssstarted
Daémonspawn 4ssarted
Daémonspawn 5
Daémonspawn 6
Daémonspawn 7ssered
Daémonspawn 8sseted
Daémonspawn 9ssalted
t [0] .isdaemontrue
t [1] .isdaemontrue
t [2] .isdaemontrue
t [3] .isdaemontrue
t [4] .isdaemontrue
t [5] .isdaemontrue
t [6] .isdaemontrue
t [7] .isdaemontrue
t [8] .isdaemontrue
t [9] .isdaemontrue
3. Especifique un objeto ThreadFactory especificando Executors.newCachedThreadPool() . De esta manera, también podemos establecer el hilo que queremos comenzar como un hilo de fondo.
/* En este ejemplo, para este constructor estático: ejecutors.newCachedThreadPool (new DaemonThreadFactory ()* Podemos pasar en un objeto ThreadFactory, por lo que podemos establecer el subproceso que queremos iniciar como un hilo de fondo a través de este método* Esto se debe notar.*/Class DaemonThactory Implementos INMESTRESS {@Override Public Thread NewThread (ejecutable Runnable R) {Thread t). Thread (r); T.SetDaemon (true); return t;}}/* En este ejemplo, en el método principal, el método ordinario en el método principal se llamará primero, "System.out.println (" Todos los Dameons iniciados ");" Por lo tanto, esta declaración principal se imprimirá durante el hilo principal. La línea principal finalizará la ejecución. (InterruptedException e) {System.out.println ("Interrupted");}} public static void main (string [] args) {ExecutorService exec = Ejecutors.NewCachedThreadPool (nuevo DaemonThreadFactory ()); DaemonFromFactory ());} System.out.println ("Todos los Dameons iniciados"); intente {TimeUnit.MillisEconds.sleep (500);} Catch (InterruptedException e) {E.PrintStackTrace ();}}}}}El resultado final de salida es:
Todos los Dameons comenzó
Thread [Thread-3,5, Main] concurrencia.daemonfromfactory@56214c1
Thread [Thread-2,5, Main] Concurrency.daemonFromFactory@5724147d
Thread [Thread-0,5, Main] concurrencia.daemonfromfactory@144fe080
Thread [Thread-1,5, Main] Concurrency.daemonFromFactory@104fa29e
Thread [Thread-8,5, Main] concurrencia.daemonfromfactory@5b069a7f
Thread [Thread-9,5, Main] concurrencia.daemonfromfactory@1a7288d1
Thread [Thread-7,5, Main] concurrencia.daemonfromfactory@25144c3e
Thread [Thread-4,5, Main] concurrencia.daemonfromfactory@288523d
Thread [Thread-6,5, Main] concurrencia.daemonfromfactory@1edae2a8
Thread [Thread-5,5, Main] concurrencia.daemonfromfactory@626007AA
Thread [Thread-3,5, Main] concurrencia.daemonfromfactory@56214c1
Thread [Thread-2,5, Main] Concurrency.daemonFromFactory@5724147d
Thread [Thread-6,5, Main] concurrencia.daemonfromfactory@1edae2a8
Thread [Thread-5,5, Main] concurrencia.daemonfromfactory@626007AA
Thread [Thread-4,5, Main] concurrencia.daemonfromfactory@288523d
Thread [Thread-9,5, Main] concurrencia.daemonfromfactory@1a7288d1
Thread [Thread-7,5, Main] concurrencia.daemonfromfactory@25144c3e
Thread [Thread-8,5, Main] concurrencia.daemonfromfactory@5b069a7f
Thread [Thread-1,5, Main] Concurrency.daemonFromFactory@104fa29e
Thread [Thread-0,5, Main] concurrencia.daemonfromfactory@144fe080
Thread [Thread-2,5, Main] Concurrency.daemonFromFactory@5724147d
Thread [Thread-3,5, Main] concurrencia.daemonfromfactory@56214c1
Thread [Thread-6,5, Main] concurrencia.daemonfromfactory@1edae2a8
Thread [Thread-1,5, Main] Concurrency.daemonFromFactory@104fa29e
Thread [Thread-0,5, Main] concurrencia.daemonfromfactory@144fe080
Thread [Thread-7,5, Main] concurrencia.daemonfromfactory@25144c3e
Thread [Thread-8,5, Main] concurrencia.daemonfromfactory@5b069a7f
Thread [Thread-5,5, Main] concurrencia.daemonfromfactory@626007AA
Thread [Thread-9,5, Main] concurrencia.daemonfromfactory@1a7288d1
Thread [Thread-4,5, Main] concurrencia.daemonfromfactory@288523d
Thread [Thread-2,5, Main] Concurrency.daemonFromFactory@5724147d
Thread [Thread-3,5, Main] concurrencia.daemonfromfactory@56214c1
Thread [Thread-8,5, Main] concurrencia.daemonfromfactory@5b069a7f
Thread [Thread-7,5, Main] concurrencia.daemonfromfactory@25144c3e
Thread [Thread-4,5, Main] concurrencia.daemonfromfactory@288523d
Thread [Thread-6,5, Main] concurrencia.daemonfromfactory@1edae2a8
Thread [Thread-1,5, Main] Concurrency.daemonFromFactory@104fa29e
Thread [Thread-0,5, Main] concurrencia.daemonfromfactory@144fe080
Thread [Thread-9,5, Main] concurrencia.daemonfromfactory@1a7288d1
Thread [Thread-5,5, Main] concurrencia.daemonfromfactory@626007AA
Thread [Thread-3,5, Main] concurrencia.daemonfromfactory@56214c1
Thread [Thread-2,5, Main] Concurrency.daemonFromFactory@5724147d
Thread [Thread-8,5, Main] concurrencia.daemonfromfactory@5b069a7f
4. En primer lugar, debe darse cuenta de que si el hilo del usuario sale repentinamente, el hilo de fondo terminará su método de ejecución sin ejecutar la cláusula finalmente.
/* Cuando llame a este programa, verá que la cláusula finalmente no se ejecutará, pero si comenta la llamada a setDaemon (), verá que la cláusula* finalmente se ejecutará.* Este comportamiento es correcto. Incluso si no quieres este comportamiento basado en la promesa que finalmente diste frente a ti. Pero este es el caso. Cuando el último hilo no background termina, el hilo de fondo se detendrá repentinamente. Porque una vez que Main () salga, el JVM cerrará inmediatamente todos los * hilos en el fondo. Debido a que no puedes cerrar los hilos de fondo de una manera elegante, apenas no son una buena idea. Los ejecutores que no son de respaldo suelen ser * una mejor manera, porque todas las tareas controladas por el ejecutor pueden cerrarse al mismo tiempo. */clase Adaemon implementa runnable {@Override public void run () {System.out.println ("Iniciar Adaemon"); intente {TimeUnit.seconds.sleep (1); } catch (interruptedException e) {System.out.println ("Salir a través de InterruptedException"); } finalmente {System.out.println ("¿Esto siempre debe ejecutarse?"); }}} public class daemonsdontrunfinally {public static void main (string [] args) {Thread t = new Thread (new Adaemon ()); T.SetDaemon (verdadero); t.Start (); }} Los resultados de la salida final son los siguientes:
Adaemon comenzando
Sin embargo, si la situación se convierte en la siguiente situación, los resultados de la salida serán diferentes nuevamente:
clase Adaemon implementa runnable {@Override public void run () {System.out.println ("iniciar Adaemon"); intente {TimeUnit.seconds.sleep (1); } catch (interruptedException e) {System.out.println ("Salir a través de InterruptedException"); } finalmente {System.out.println ("¿Esto siempre debe ejecutarse?"); }}} public class daemonsdontrunfinally {public static void main (string [] args) {Thread t = new Thread (new Adaemon ()); T.SetDaemon (verdadero); t.Start (); intente {TimeUnit.seconds.sleep (1); } catch (InterruptedException e) {E.PrintStackTrace (); }}}Dado que el hilo principal no sale repentinamente, el hilo de fondo obtiene el tiempo de ejecución durante el hilo principal que duerme, por lo que el resultado de la impresión final es:
Adaemon comenzando
¿Esto siempre debería funcionar?
Lo anterior es todo el contenido de este artículo sobre el análisis de instancias de hilo de fondo en Java, y espero que sea útil para todos. Los amigos interesados pueden continuar referiéndose a otros temas relacionados en este sitio. Si hay alguna deficiencia, deje un mensaje para señalarlo. ¡Gracias amigos por su apoyo para este sitio!