Javaでは、2つのスレッドが通常あります:ユーザスレッドとスレッドガード(また、サービススレッドと呼ばれる)
ユーザスレッドへのThread.setDaemon(false)をセットすることにより
(真)Thread.setDaemonスルーがデーモンスレッドを設定する
スレッドがであることを属性を設定しますスレッドが開始される前に、それ以外の場合はないIllegalThreadStateException異常が報告され
ますが、ユーザスレッドのために、デフォルトのスレッド属性を設定しない場合
ユーザスレッドとデーモンスレッド間の差異:
メインスレッドを実行し続けますエンドユーザスレッド1、JVMの生存
2.どのユーザスレッドがデーモンスレッドではないがある場合は、JVMの終了(すべてのスレッドが終了しました)
デーモン(デーモン)は、バックグラウンドでの特別なプロセスを実行しています。これは、制御端子とは無関係であり、定期的にいくつかのタスクまたは処理を待ついくつかのイベントを実行します。そのデーモンスレッドは、端末に依存しますが、システムに依存しない、そしてシステム「ライブと一緒に死にます。」Javaのデーモンスレッドがそれのように見えること。JVMのすべてのスレッドがデーモンスレッドであれば、JVMは引き出すことができ、一つ以上の非デーモンスレッドがある場合、JVMは終了しません。
デーモンスレッドは静かになど、バックグラウンドでいくつかの体系的なサービスを行う、特別なスレッドであるガベージコレクションスレッド、JITのスレッドがあるデーモンスレッドが。対応しているユーザスレッド、ユーザスレッドがワーカースレッドのシステムとして理解することができ、それは操作手順を完了する必要が完了します。ユーザスレッドすべてを超える場合には、業務を完了するために必要なプログラムが完了したことを意味するには、システムを引き出すことができます。場合にのみ、デーモンシステム、Java仮想マシンに自動的に終了しますので。
Javaスレッドは、ユーザースレッドとデーモンスレッドに分割され、真の表現にデーモンスレッド属性がデーモンスレッドで、虚偽の表現は、ユーザスレッドです。
ここでは、スレッドデーモン機能のいくつかを見てみましょう。
プログラムの場合にのみ、デーモンスレッド、システムは自動的に終了
パブリック クラスDEMO1 { パブリック 静的 クラス T1が延びスレッド{ 公共Tlの(文字列名){ スーパー;(名) } @Override 公共 ボイドRUN(){ System.out.printlnは(この .getName()+ "開始" +を(この .isDaemon()「デーモンスレッドIである」?「私はユーザスレッド午前」)); 一方、(真の); } } パブリック 静的 ボイドメイン(文字列[]引数){ TlのT1 = 新しい新TL( "子スレッド1" ); t1.start(); のSystem.out.println( "メインスレッドを終了" ); } }
上記のコードを実行すると、以下の結果:
あなたは、メインスレッドが終了した見ることができますが、ため、プログラムが終了することはできません:1つのスレッドがユーザスレッドで、内部の死のサイクルがあり、それは、動作して終わりではありませんでした。
次のコードを見てください:
パブリック クラスDEMO2 { パブリック 静的 クラス T1が延びスレッド{ 公共Tlの(文字列名){ スーパー;(名) } @Override 公共 ボイドRUN(){ System.out.printlnは(この .getName()+ "開始" +を(この .isDaemon()「デーモンスレッドIである」?「私はユーザスレッド午前」)); 一方、(真の); } } パブリック 静的 ボイドメイン(文字列[]引数){ TlのT1 = 新しい新TL( "子スレッド1。" ); t1.setDaemon(真の); t1.start(); System.out.printlnは( "メインスレッドを終了します" ); } }
結果:
プログラムが正常に完了することができ、によってコードt1.setDaemon(true);
デーモンスレッドへのT1スレッド、mainメソッドが終了した場合の後、メインスレッドの実行、プログラムが終了します。
結論:このプログラムは、すべてのユーザーのスレッドを終了すると関係なく、デーモンスレッドの終了は、システムが自動的に終了するかどうかの。
デーモンスレッドはstart()メソッドの前に行わなければなりません
輸入java.util.concurrent.TimeUnit。 パブリック クラスDemo3 { 公共 静的 ボイドメイン(文字列[]引数){ スレッドT1 = 新しいスレッド(){ @Override 公共 ボイドラン(){ 試み{ TimeUnit.SECONDS.sleep( 10 )。 } キャッチ(InterruptedExceptionある電子){ e.printStackTrace(); } } }。 t1.start(); t1.setDaemon(真の); } }
t1.setDaemon(true);
start()メソッドが実行された後、T1で行われる次のように異常な結果が報告されます。
スレッドのデーモンのデフォルト値
私たちは、スレッドを作成するためにソースコードを見て、位置のinit Threadクラス()メソッド:
Thread parent = currentThread();
this.daemon = parent.isDaemon();
デフォルト値は、と言うことですdameonの親スレッドデーモン、ある親スレッドがユーザスレッドである場合、子スレッドが親スレッドがデーモンスレッドである場合、子スレッドのデフォルトはデーモンスレッドで、デフォルトのユーザサイトです。
サンプルコード:
import java.util.concurrent.TimeUnit; public class Demo4 { public static class T1 extends Thread { public T1(String name) { super(name); } @Override public void run() { System.out.println(this.getName() + ".daemon:" + this.isDaemon()); } } public static void main(String[] args) throws InterruptedException { System.out.println(Thread.currentThread().getName() + ".daemon:" + Thread.currentThread().isDaemon()); T1 t1 = new T1("t1"); t1.start(); Thread t2 = new Thread() { @Override public void run() { System.out.println(this.getName() + ".daemon:" + this.isDaemon()); T1 t3 = new T1("t3"); t3.start(); } }; t2.setName("t2"); t2.setDaemon(true); t2.start(); TimeUnit.SECONDS.sleep(2); } }
运行代码,输出:
main.daemon:false t1.daemon:false t2.daemon:true t3.daemon:true
t1是由主线程(main方法所在的线程)创建的,main线程是t1的父线程,所以t1.daemon为false,说明t1是用户线程。
t2线程调用了setDaemon(true);
将其设为守护线程,t3是由t2创建的,所以t3默认线程类型和t2一样,t2.daemon为true。
守护线程适用场景
针对于守护线程的特点,java 守护线程通常可用于开发一些为其它用户线程服务的功能。比如说心跳检测,事件监听等。Java 中最有名的守护进程当属GC(垃圾回收)
总结
- java中的线程分为用户线程和守护线程
- 程序中的所有的用户线程结束之后,不管守护线程处于什么状态,java虚拟机都会自动退出
- 调用线程的实例方法setDaemon()来设置线程是否是守护线程
- setDaemon()方法必须在线程的start()方法之前调用,在后面调用会报异常,并且不起效
- 线程的daemon默认值和其父线程一样