mian()メソッドの作成から言えば、デーモンスレッドと非デーモンスレッド

47274 ワード

  • mian()メソッドを作成するには、どのようなことをしましたか?
  • デーモンスレッドおよび非デーモンスレッド
  • デーモンスレッド
  • を作成する

    mian()メソッドを作成するにはどのようなことをしましたか?

  • 作成メソッドmain()メソッドを作成した場合、JVMはどのようなことをしてくれましたか?単純にmianスレッドを開き、mian()メソッドのメソッドボディを実行するだけですか?現在のスレッド状況
  • をコードで検証する
    import java.lang.management.ManagementFactory;
    import java.lang.management.ThreadInfo;
    import java.lang.management.ThreadMXBean;
    import java.util.Scanner;
    
    
    public class HelloWorld {
        public static void main(String[] args) {
    
            System.out.println("---------------main ----------------------");
            //  MXBean
            ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
            //  monitor synchronizer 
            //  
            ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);
            System.out.println("------------- ------------");
            for (ThreadInfo threadInfo : threadInfos) {
            //  id 
                System.out.println("[" + threadInfo.getThreadId() + "]" + "------->" + threadInfo.getThreadName());
            }
            System.out.println("main ");
            Scanner scanner = new Scanner(System.in);
            scanner.next();
        }
    }
    
  • 運転結果
  • ---------------main ------------------
    ------------- -----------------
    [6]------->Monitor Ctrl-Break
    [5]------->Attach Listener
    [4]------->Signal Dispatcher
    [3]------->Finalizer
    [2]------->Reference Handler
    [1]------->main
    main 
    
  • 結果の分析から分かるように、簡単なmain()方法であり、JVMはmainスレッド以外の5つのスレッドを作成してくれた.(作成スレッド数はJDKバージョンおよびIDEに関係する、ここではJDK 1.7,Idea)Monitor Ctrl-Break:Idea Runプログラムを使用してこのスレッドをForkし、Eclipseはしない.Attach Listener:外部からのコマンドを受信し、そのコマンドを実行し、結果を送信者に返す.Signal Dispatcher:Attach Listenerがコマンドの受信に成功すると、signal dispatherスレッドに渡されて、それぞれの異なるモジュール処理コマンドに配布され、処理結果が返される.Finalizer:このスレッドはmainスレッドの後に作成され、その優先度は10であり、主にゴミ収集前にオブジェクトを呼び出すfinalize()メソッドに用いられる.4つの注意点があります.
  • ゴミ収集を開始するときのみfinalize()メソッドの呼び出しが開始する、すべてのオブジェクトのfinalize()メソッドが実行されるわけではない.
  • このスレッドもdaemonスレッドであるため、仮想マシンに他のdaemon以外のスレッドがない場合、そのスレッドがfinalize()メソッドを実行したかどうかにかかわらず、JVMは終了する.
  • JVMはゴミ収集時に参照を失ったオブジェクトをFinalizerオブジェクト(Referenceの実装)に包装し、Finalizerスレッドによって処理されるReferenceQueueに入れる.最後にこのFinalizerオブジェクトの参照をnullとしてゴミ収集器で回収する.
  • JVMはなぜ単独でfinalize()メソッドを実行するのですか?JVMのゴミ収集スレッドが自分で行う場合、finalize()メソッドでの誤操作によりGCスレッドが停止または制御不能になる可能性が高いため、GCスレッドにとって災害
  • であるReference Handler:JVMはmainスレッドを作成した後にReference Handlerスレッドを作成し、その優先度は10で最も高く、主に参照オブジェクト自体(ソフトリファレンス、弱リファレンス、ダミーリファレンス)のゴミ回収問題を処理するために使用されます.

    デーモンスレッドと非デーモンスレッド

  • の2種類のスレッドjavaには2種類のスレッド、ガードスレッドと非ガードスレッド(ユーザスレッド)がある.
  • 簡単に言えば、デーモンスレッドはデーモンのように、プログラムの実行時に共通のサービスなどを提供する.私たちがあまり注目する必要はありません.e.g:JVMのゴミ回収スレッドはデーモンスレッドである.すべての非デーモンスレッドが終了すると、JVMは自動的に終了し、すべてのデーモンスレッドを殺す.
  • 非デーモンスレッド、すなわちユーザスレッドである.一般的にはユーザによって作成する.ユーザスレッドがまだ実行する限り、JVMは終了しない.

  • スレッドのプロパティを表示さっきのmain()メソッドを例に、JDKが持っているツールを使用してスレッドのプロパティを表示します.
  • jps(Java Virtual Machine Process Status Tool):JVMのプロセスを表示するためのコマンド:jps [options] [hostid]、hostidパラメータが空のデフォルトでローカルにアクセスする仮想マシン.optionsパラメータは空でもよい、共通パラメータは-lであり、全パス名のプロセスを表示する.

  • $ jps
    448336 Launcher
    398940
    453576 Launcher
    454576 HelloWorld
    452796 Jps
    
    $ jps -l
    448336 org.jetbrains.jps.cmdline.Launcher
    398940
    451576 sun.tools.jps.Jps
    453576 org.jetbrains.jps.cmdline.Launcher
    454576 com.cxw.HelloWorld
    

    HelloWorld対応pidを見つけ、jstackツールを使用して対応するスレッドのスタック情報を表示します.
  • jstackは、JDKに備える、指定スレッドIDのスタック情報を表示するツールである.
  • //  :jstack pid
    $ jstack 454576
    

    コンソール印刷情報は次のとおりです.
    //  daemon 
    "Monitor Ctrl-Break" daemon prio=6 tid=0x000000000e4b8800 nid=0x6f198 runnable [0x000000000fade000]
       java.lang.Thread.State: RUNNABLE
            at java.net.SocketInputStream.socketRead0(Native Method)
            at java.net.SocketInputStream.read(SocketInputStream.java:150)
            at java.net.SocketInputStream.read(SocketInputStream.java:121)
            at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
            at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
            at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
            - locked <0x00000000d602bed0> (a java.io.InputStreamReader)
            at java.io.InputStreamReader.read(InputStreamReader.java:184)
            at java.io.BufferedReader.fill(BufferedReader.java:154)
            at java.io.BufferedReader.readLine(BufferedReader.java:317)
            - locked <0x00000000d602bed0> (a java.io.InputStreamReader)
            at java.io.BufferedReader.readLine(BufferedReader.java:382)
            at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)
    //  Attach Listener
    "Attach Listener" daemon prio=10 tid=0x000000000e440800 nid=0x6d85c waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    //  Signal Dispatcher
    "Signal Dispatcher" daemon prio=10 tid=0x000000000e43d000 nid=0x6f208 runnable [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    //  Finalizer
    "Finalizer" daemon prio=8 tid=0x000000000e3b9800 nid=0x6d1d4 in Object.wait() [0x000000000f7df000]
       java.lang.Thread.State: WAITING (on object monitor)
            at java.lang.Object.wait(Native Method)
            - waiting on <0x00000000d5eb57f0> (a java.lang.ref.ReferenceQueue$Lock)
            at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
            - locked <0x00000000d5eb57f0> (a java.lang.ref.ReferenceQueue$Lock)
            at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
            at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:177)
    //  Reference Handler
    "Reference Handler" daemon prio=10 tid=0x000000000e3b0800 nid=0x6a3a0 in Object.wait() [0x000000000f6df000]
       java.lang.Thread.State: WAITING (on object monitor)
            at java.lang.Object.wait(Native Method)
            - waiting on <0x00000000d5eb5370> (a java.lang.ref.Reference$Lock)
            at java.lang.Object.wait(Object.java:503)
            at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
            - locked <0x00000000d5eb5370> (a java.lang.ref.Reference$Lock)
    //  main
    "main" prio=6 tid=0x000000000542e000 nid=0x6de30 runnable [0x000000000370f000]
       java.lang.Thread.State: RUNNABLE
            at java.io.FileInputStream.readBytes(Native Method)
            at java.io.FileInputStream.read(FileInputStream.java:242)
            at java.io.BufferedInputStream.read1(BufferedInputStream.java:273)
            at java.io.BufferedInputStream.read(BufferedInputStream.java:334)
            - locked <0x00000000d5f07f30> (a java.io.BufferedInputStream)
            at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
            at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
            at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
            - locked <0x00000000d5fedcd8> (a java.io.InputStreamReader)
            at java.io.InputStreamReader.read(InputStreamReader.java:184)
            at java.io.Reader.read(Reader.java:100)
            at java.util.Scanner.readInput(Scanner.java:849)
            at java.util.Scanner.next(Scanner.java:1414)
            at com.cxw.HelloWorld.main(HelloWorld.java:24)
    

    デーモンスレッドの作成

  • デーモンスレッドを作成し、直接コードをアップロードします.
  • public class DaemonThreadDemo {
    
        public class MyDaemon implements Runnable {
    
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    System.out.println(" "+i+" ");
                }
            }
        }
    
        /**
         *  
         * @throws IOException
         */
        @Test
        public void DaemonThreadTest() throws IOException {
            Thread thread = new Thread(new MyDaemon());
            // setDaemon(true) 
            thread.setDaemon(true);
            thread.start();
            // isDaemon() 
            if (thread.isDaemon()) {
                System.out.println(" ");
            } else {
                System.out.println(" ");
            }
            System.in.read();
        }
    
    }
    

    実行結果
     
     0 
     1 
     2 
     3 
     4 
    

    スレッドを実行する前にsetDaemon()メソッドを使用して、スレッドをデーモンスレッドに設定.
  • デーモンスレッド作成スレッドまたはデーモンスレッド
  • public class DaemonThreadDemo {
    
        public class MyDaemon implements Runnable {
    
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    System.out.println(" " + i + " ");
                }
                Thread subThread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        //  fork 
                        System.out.println(" , " + Thread.currentThread().isDaemon());
                    }
                });
                subThread.start();
            }
        }
    
        /**
         *  
         *
         * @throws IOException
         */
        @Test
        public void DaemonThreadTest() throws IOException {
            Thread thread = new Thread(new MyDaemon());
            // setDaemon(true) 
            thread.setDaemon(true);
            thread.start();
            // isDaemon() 
            if (thread.isDaemon()) {
                System.out.println(" ");
            } else {
                System.out.println(" ");
            }
            System.in.read();
        }
    
    }
    

    実行結果
     
     0 
     1 
     2 
     3 
     4 
     , true
    

    ガードスレッドにおいてforkが出すサブスレッドは依然としてガードスレッドであることがわかる.
  • ユーザースレッドを作成して、
  • と比較します.
    public class DaemonThreadDemo {
    
        @Test
        public void ThreadDemo() {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(" , "+Thread.currentThread().isDaemon());
                }
            });
            thread.start();
        }
    }
    

    実行結果
     , false
    

    main()メソッドおよびJunitのTestメソッドでは、setDaemon()メソッドで設定スレッドとmain()メソッドは使用されず、Testメソッドは同じスレッド属性、すなわち非デーモンスレッドを保持することが明らかである.記事リファレンス:JVM内部実行スレッドの説明