logbackでデーモンスレッド - の重要性についての知識に基づいて

logbackで使用されるデーモンスレッド

私はJavaアプリケーションでの問題についてお話しましょう、非同期のアペンダは、どのようにメインスレッドの終わりにされlogback停止に来ましたの?

リプレイ

私がしていたlogbackテストケースと、このコードと書いたlogbackコンフィギュレーションを:

// 一个测试类,main函数中简单的打印了几行日志
public class Test {

    private static final Logger LOGGER = LoggerFactory.getLogger(Test.class);

    public static void main(String[] args) {
        LOGGER.info("test log 1");
        LOGGER.info("test log 2");
    }

}

これは私が使用するものであるlogback構成をされてroot-logger2で構成されappender、1 ConsoleAppenderコンソールに出力の内容を記録します、と他のがに設定されている、それは、ログファイル出力の内容に非同期方式を使用していますAsyncAppenderFileAppender

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>/usr/local/test.log</file>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="FILE" />
    </appender>
    <root level="debug">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="ASYNC"/>
    </root>
</configuration>

私は正常に行われた場合Test.main()、ウォッチコンソール出力ファイルは、通常のログです。その後、観察するためにAsyncAppender原則を、私は午前中にAsyncAppender、親クラスAsyncAppenderBaseの一般的な原則を見て、中:呼び出されるメソッドは、実際には、私がスレッドを開始しました。インターセプト法より重要なコードはであるキューをブロックから取得したサイクル、私は具体的な希望にここにブレークポイント、追撃を果たし、オーバー見てAsyncAppenderBasestart()worker.start()Worker.run()whileILoggerEventAppender

while (parent.isStarted()) {
    try {
        E e = parent.blockingQueue.take();
        // 这里打了断点
        aai.appendLoopOnAppenders(e);
    } catch (InterruptedException ie) {
        break;
    }
}

ブレークポイントに到達すると、Javaアプリケーションが終わった全体突然見つけ、ステッパーをクリックして、しばらくの変数のために観察します。いずれかの例外が発生しなければ私は必ずしもブレークポイントで終わらない、この場合に多くの時間を再試行して、可能性ダウンいくつかの手順を、しかし、デバッグモードでは、Javaアプリケーションは、いくつかの点での兆候が存在しないだろう「正常終了」は

私は、メインスレッドがオーバー実行しなければならないことを示す、ログの2行がプリントアウトされたビットコンソールを確認しなければならなかったが、私は知識ベースが持っていた子スレッドが終了していない場合、それは子スレッドを待ちます、Javaのメインスレッドの終わりに後、JVMは終了タスクを実行します。(ここで私はデーモンスレッドの概念を覚えていません)

上記の結論は間違っています

それまでに望んでいたjstackとき、それを観察するためにmain-Thread:スレッドの終了後に最終的に状況は何です

私たちは、ここで見つけます:

DestroyJavaVMで、実際にスレッドRUNNABLE段階だけでなく、サブスレッドの実行中に、ああ、なぜそれが開始

疑い別の表情でAsyncAppender-Worker-ASYNCも非同期ログ印刷ジョブスレッド、及びあるスレッド、RUNNABLEそれがあると思われる状態、守护线程(daemon)Javaスレッドの基本それを考える、ユーザスレッドスレッドガード、から直接ここに掲載ThreadsetDaemon仕方コードのコメントは、言った:ユーザスレッドやデーモンスレッドとして、このスレッドをマークし、唯一の現在実行中のスレッド、すべての時間のデーモンスレッドでJVMは、終了します。

見てください方法:AsyncAppenderBasestart()

我々は、それが、見ることができるworkerために指定されているdaemon実際には、ここでの問題は解決されるだろう、スレッド。

結論

複雑ではありません遭遇する問題は、問題は主に知識ベースであります

デーモン・スレッドのみならば、;ジャワ、能力上のユーザスレッドとスレッドガードをマルチスレッドと違いはありません、最も重要な違いは、生き残ったユーザスレッドがある場合と、JVMが終了すると、終了していないということですJVMは、すべてのデーモンスレッドを殺す、そして終了します。

PS:
誰がどのくらいI DEBUGを知っています。ただ、理解の範囲を超えました!ほとんどそれは形而上学だと思いました

おすすめ

転載: www.cnblogs.com/shiyu404/p/11928247.html