目次
1. デフォルトのユーザー スレッド
デーモン スレッド (デーモン スレッド) は、バックグラウンド スレッドまたはサービス スレッドとも呼ばれます。 #、プログラム内のすべてのユーザー スレッドが終了すると、デーモン スレッドも終了します。
メソッドを通じてスレッド タイプをデーモン スレッドに変更できます。 ,
は、スレッド プール内の各スレッドを定義します。各スレッドのスレッド タイプが決定されます。具体的な実装コードは次のとおりです。
次に、スレッドを作成し、このスレッドをそれぞれユーザー スレッドとデーモン スレッドとして設定し、各スレッドで
を実行するだけです。ループ (合計 10 回実行 情報の印刷、各印刷後に 100 ミリ秒スリープ)、
3.3 小结
4.守护线程注意事项
4.1 setDaemon 执行顺序
4.2 守护线程的子线程
4.3 join 与守护线程
5.守护线程应用场景
6.守护线程的执行优先级
ホームページ Java &#&チュートリアル Java でユーザー スレッドとデーモン スレッドを使用する方法

Java でユーザー スレッドとデーモン スレッドを使用する方法

May 13, 2023 am 11:28 AM
java

    1. デフォルトのユーザー スレッド

    Java 言語では、スレッドであってもスレッド プールであっても、デフォルトはユーザー スレッドです。 したがって、ユーザー スレッドは通常のスレッドとも呼ばれます。

    スレッドを例に挙げます。スレッドがデーモン スレッドであるかどうかを確認したい場合は、isDaemon() メソッドを呼び出してクエリを実行するだけです。クエリ値が # の場合は、 ##false の場合、これはデーモン スレッドではないことを意味するため、当然ユーザー スレッドに属します。

    次のコードが表示されます:

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("我是子线程");
            }
        });
        System.out.println("子线程==守护线程:" + thread.isDaemon());
        System.out.println("主线程==守护线程:" + Thread.currentThread().isDaemon());
    }
    ログイン後にコピー

    上記のプログラムの実行結果は次のとおりです。

    Java でユーザー スレッドとデーモン スレッドを使用する方法

    上記の結果からわかるように、

    デフォルトでは、メインスレッドと作成された新しいスレッドは両方ともユーザー スレッドです。

    PS: Thread.currentThread() は、現在のコードを実行しているスレッド インスタンスを取得することを意味します。

    2. 積極的にデーモン スレッドに変更します

    デーモン スレッド (デーモン スレッド) は、バックグラウンド スレッドまたはサービス スレッドとも呼ばれます。 #、プログラム内のすべてのユーザー スレッドが終了すると、デーモン スレッドも終了します。

    デーモンスレッドの役割は「ウェイター」のようなもので、ユーザースレッドの役割は「顧客」のようなもので、すべての「顧客」が退場すると(すべての実行が終了すると)、「ウェイター」は(デーモンスレッド) も存在意味がないため、プログラム内のすべてのユーザースレッドが実行を終了すると、デーモンスレッドがまだ動作しているかどうかに関係なく、ユーザースレッドとともに終了し、プログラム全体も終了します。ランニングを終了します。

    デフォルトのユーザー スレッドをデーモン スレッドに変更するにはどうすればよいですか?

    この質問には 2 つの状況で回答する必要があります。まず、スレッドの場合は、setDaemon(true) を設定することで、ユーザー スレッドをデーモン スレッドに直接変更できます。メソッドを作成し、スレッド プールの場合は

    ThreadFactory

    を使用してスレッド プール内の各スレッドをデーモン スレッドにする必要があります。次に、これを個別に実装します。 2.1 スレッドをデーモン スレッドとして設定するスレッドを使用している場合は、

    setDaemon(true)

    メソッドを通じてスレッド タイプをデーモン スレッドに変更できます。 ,

    次のコードを示します:

    <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'> public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new Runnable() { @Override public void run() { System.out.println(&quot;我是子线程&quot;); } }); // 设置子线程为守护线程 thread.setDaemon(true); System.out.println(&quot;子线程==守护线程:&quot; + thread.isDaemon()); System.out.println(&quot;主线程==守护线程:&quot; + Thread.currentThread().isDaemon()); }</pre><div class="contentsignin">ログイン後にコピー</div></div>上記プログラムの実行結果は次のとおりです:

    2.2スレッド プールをデーモン スレッドとして設定する

    Java でユーザー スレッドとデーモン スレッドを使用する方法スレッド プールをデーモン スレッドとして設定するのは比較的面倒です。スレッド プール内のすべてのスレッドをデーモン スレッドとして設定する必要があります。このとき、

    ThreadFactory

    は、スレッド プール内の各スレッドを定義します。各スレッドのスレッド タイプが決定されます。具体的な実装コードは次のとおりです。

    // 创建固定个数的线程池
    ExecutorService threadPool = Executors.newFixedThreadPool(10, new ThreadFactory() {
        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r);
            // 设置线程为守护线程
            t.setDaemon(false);
            return t;
        }
    });
    ログイン後にコピー

    次の図に示すように:

    上の図に示すように、私が作成したプログラム全体には 10 個のデーモン スレッドがあることがわかります。スレッド プールを作成するための他のいくつかの設定も同様であり、これらはすべて

    ThreadFactoryJava でユーザー スレッドとデーモン スレッドを使用する方法 を通じて均一に設定されるため、ここでは 1 つずつリストしません。

    3. デーモン スレッド VS ユーザー スレッドこれまでの学習により、2 つの異なるスレッド タイプを作成できます。次に、小さな例を使用して見てみましょう。

    次に、スレッドを作成し、このスレッドをそれぞれユーザー スレッドとデーモン スレッドとして設定し、各スレッドで

    for

    ループを実行し、毎回合計 10 回情報を出力します。 100 ミリ秒スリープして、プログラムの実行結果を観察します。

    3.1 ユーザー スレッド新しく作成されたスレッドはデフォルトでユーザー スレッドとなるため、スレッドに対して特別な処理を実行する必要はありません。

    for

    を実行するだけです。ループ (合計 10 回実行 情報の印刷、各印刷後に 100 ミリ秒スリープ)、

    実装コードは次のとおりです。

    <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>/** * Author:Java中文社群 */ public class DaemonExample { public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new Runnable() { @Override public void run() { for (int i = 1; i &lt;= 10; i++) { // 打印 i 信息 System.out.println(&quot;i:&quot; + i); try { // 休眠 100 毫秒 Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }); // 启动线程 thread.start(); } }</pre><div class="contentsignin">ログイン後にコピー</div></div>上記プログラムの実行結果は次のとおりです。

    上記の結果から、プログラムが 10 回印刷を実行するまでプロセスは正常に終了しないことがわかります。

    Java でユーザー スレッドとデーモン スレッドを使用する方法3.2 デーモン スレッド

    /**
     * Author:Java中文社群
     */
    public class DaemonExample {
        public static void main(String[] args) throws InterruptedException {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 1; i <= 10; i++) {
                        // 打印 i 信息
                        System.out.println("i:" + i);
                        try {
                            // 休眠 100 毫秒
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
            // 设置为守护线程
            thread.setDaemon(true);
            // 启动线程
            thread.start();
        }
    }
    ログイン後にコピー

    上記のプログラムの実行結果は次のとおりです。

    ご覧のとおり上記の結果から、スレッドがデーモン スレッドとして設定されている場合、プログラム全体は、デーモン スレッド

    forJava でユーザー スレッドとデーモン スレッドを使用する方法 が 10 回循環してから終了するのを待たずに、メイン スレッドが終了すると、デーモン スレッドが終了します。サイクルを 1 回だけ実行して終了する これは、デーモン スレッドとユーザー スレッドの違いを示しています。

    3.3 小结

    守护线程是为用户线程服务的,当一个程序中的所有用户线程都执行完成之后程序就会结束运行,程序结束运行时不会管守护线程是否正在运行,由此我们可以看出守护线程在 Java 体系中权重是比较低的。

    4.守护线程注意事项

    守护线程的使用需要注意以下三个问题:

    • 守护线程的设置 setDaemon(true) 必须要放在线程的 start() 之前,否则程序会报错。

    • 在守护线程中创建的所有子线程都是守护线程。

    • 使用 jojn() 方法会等待一个线程执行完,无论此线程是用户线程还是守护线程。

    接下来我们分别演示一下,以上的注意事项。

    4.1 setDaemon 执行顺序

    当我们将 setDaemon(true) 设置在 start() 之后,如下代码所示:

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 1; i <= 10; i++) {
                    // 打印 i 信息
                    System.out.println("i:" + i + ",isDaemon:" +
                                Thread.currentThread().isDaemon());
                    try {
                        // 休眠 100 毫秒
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        // 启动线程
        thread.start();
        // 设置为守护线程
        thread.setDaemon(true);
    }
    ログイン後にコピー

    以上程序执行结果如下:

    Java でユーザー スレッドとデーモン スレッドを使用する方法

    从上述结果可以看出,当我们将 setDaemon(true) 设置在 start() 之后,不但程序的执行会报错,而且设置的守护线程也不会生效。

    4.2 守护线程的子线程

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                Thread thread2 = new Thread(new Runnable() {
                    @Override
                    public void run() {
    
                    }
                });
                System.out.println("守护线程的子线程 thread2 isDaemon:" +
                                  thread2.isDaemon());
            }
        });
        // 设置为守护线程
        thread.setDaemon(true);
        // 启动线程
        thread.start();
    
        Thread.sleep(1000);
    }
    ログイン後にコピー

    以上程序执行结果如下:

    Java でユーザー スレッドとデーモン スレッドを使用する方法

    从上述结果可以看出,守护线程中创建的子线程,默认情况下也属于守护线程

    4.3 join 与守护线程

    通过 3.2 部分的内容我们可以看出,默认情况下程序结束并不会等待守护线程执行完,而当我们调用线程的等待方法 join() 时,执行的结果就会和 3.2 的结果有所不同,下面我们一起来看吧,

    示例代码如下:

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 1; i <= 10; i++) {
                    // 打印 i 信息
                    System.out.println("i:" + i);
                    try {
                        // 休眠 100 毫秒
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        // 设置为守护线程
        thread.setDaemon(true);
        // 启动线程
        thread.start();
        // 等待线程执行完
        thread.join();
        System.out.println("子线程==守护线程:" + thread.isDaemon());
        System.out.println("主线程==守护线程:" + Thread.currentThread().isDaemon());
    }
    ログイン後にコピー

    以上程序执行结果如下:

    Java でユーザー スレッドとデーモン スレッドを使用する方法

    通过上述结果我们可以看出,即使是守护线程,当程序中调用 join() 方法时,程序依然会等待守护线程执行完成之后再结束进程。

    5.守护线程应用场景

    守护线程的典型应用场景就是垃圾回收线程,当然还有一些场景也非常适合使用守护线程,比如服务器端的健康检测功能,对于一个服务器来说健康检测功能属于非核心非主流的服务业务,像这种为了主要业务服务的业务功能就非常合适使用守护线程,当程序中的主要业务都执行完成之后,服务业务也会跟随者一起销毁。

    6.守护线程的执行优先级

    首先来说,线程的类型(用户线程或守护线程)并不影响线程执行的优先级,如下代码所示,定义一个用户线程和守护线程,分别执行 10 万次循环,通过观察最后的打印结果来确认线程类型对程序执行优先级的影响。

    public class DaemonExample {
        private static final int count = 100000;
        public static void main(String[] args) throws InterruptedException {
            // 定义任务
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < count; i++) {
                        System.out.println("执行线程:" + Thread.currentThread().getName());
                    }
                }
            };
            // 创建守护线程 t1
            Thread t1 = new Thread(runnable, "t1");
            // 设置为守护线程
            t1.setDaemon(true);
            // 启动线程
            t1.start();
            // 创建用户线程 t2
            Thread t2 = new Thread(runnable, "t2");
            // 启动线程
            t2.start();
        }
    }
    ログイン後にコピー

    以上程序执行结果如下:

    Java でユーザー スレッドとデーモン スレッドを使用する方法

    通过上述结果可以看出,线程的类型不管是守护线程还是用户线程对程序执行的优先级是没有任何影响的,而当我们将 t2 的优先级调整为最大时,整个程序的运行结果就完全不同了,

    如下代码所示:

    public class DaemonExample {
        private static final int count = 100000;
        public static void main(String[] args) throws InterruptedException {
            // 定义任务
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < count; i++) {
                        System.out.println("执行线程:" + Thread.currentThread().getName());
                    }
                }
            };
            // 创建守护线程 t1
            Thread t1 = new Thread(runnable, "t1");
            // 设置为守护线程
            t1.setDaemon(true);
            // 启动线程
            t1.start();
            // 创建用户线程 t2
            Thread t2 = new Thread(runnable, "t2");
            // 设置 t2 的优先级为最高
            t2.setPriority(Thread.MAX_PRIORITY);
            // 启动线程
            t2.start();
        }
    }
    ログイン後にコピー

    以上程序执行结果如下: 

    Java でユーザー スレッドとデーモン スレッドを使用する方法

    00000000 通过上述的结果可以看出,程序的类型和程序执行的优先级是没有任何关系,当新创建的线程默认的优先级都是 5 时,无论是守护线程还是用户线程,它们执行的优先级都是相同的,当将二者的优先级设置不同时,执行的结果也会随之改变(优先级设置的越高,最早被执行的概率也越大)。

    以上がJava でユーザー スレッドとデーモン スレッドを使用する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    このウェブサイトの声明
    この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

    ホットAIツール

    Undresser.AI Undress

    Undresser.AI Undress

    リアルなヌード写真を作成する AI 搭載アプリ

    AI Clothes Remover

    AI Clothes Remover

    写真から衣服を削除するオンライン AI ツール。

    Undress AI Tool

    Undress AI Tool

    脱衣画像を無料で

    Clothoff.io

    Clothoff.io

    AI衣類リムーバー

    Video Face Swap

    Video Face Swap

    完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

    ホットツール

    メモ帳++7.3.1

    メモ帳++7.3.1

    使いやすく無料のコードエディター

    SublimeText3 中国語版

    SublimeText3 中国語版

    中国語版、とても使いやすい

    ゼンドスタジオ 13.0.1

    ゼンドスタジオ 13.0.1

    強力な PHP 統合開発環境

    ドリームウィーバー CS6

    ドリームウィーバー CS6

    ビジュアル Web 開発ツール

    SublimeText3 Mac版

    SublimeText3 Mac版

    神レベルのコード編集ソフト(SublimeText3)

    Javaの完全数 Javaの完全数 Aug 30, 2024 pm 04:28 PM

    Java における完全数のガイド。ここでは、定義、Java で完全数を確認する方法、コード実装の例について説明します。

    ジャワのウェカ ジャワのウェカ Aug 30, 2024 pm 04:28 PM

    Java の Weka へのガイド。ここでは、weka java の概要、使い方、プラットフォームの種類、利点について例を交えて説明します。

    Javaのスミス番号 Javaのスミス番号 Aug 30, 2024 pm 04:28 PM

    Java のスミス番号のガイド。ここでは定義、Java でスミス番号を確認する方法について説明します。コード実装の例。

    Java Springのインタビューの質問 Java Springのインタビューの質問 Aug 30, 2024 pm 04:29 PM

    この記事では、Java Spring の面接で最もよく聞かれる質問とその詳細な回答をまとめました。面接を突破できるように。

    Java 8 Stream Foreachから休憩または戻ってきますか? Java 8 Stream Foreachから休憩または戻ってきますか? Feb 07, 2025 pm 12:09 PM

    Java 8は、Stream APIを導入し、データ収集を処理する強力で表現力のある方法を提供します。ただし、ストリームを使用する際の一般的な質問は次のとおりです。 従来のループにより、早期の中断やリターンが可能になりますが、StreamのForeachメソッドはこの方法を直接サポートしていません。この記事では、理由を説明し、ストリーム処理システムに早期終了を実装するための代替方法を調査します。 さらに読み取り:JavaストリームAPIの改善 ストリームを理解してください Foreachメソッドは、ストリーム内の各要素で1つの操作を実行する端末操作です。その設計意図はです

    Java での日付までのタイムスタンプ Java での日付までのタイムスタンプ Aug 30, 2024 pm 04:28 PM

    Java での日付までのタイムスタンプに関するガイド。ここでは、Java でタイムスタンプを日付に変換する方法とその概要について、例とともに説明します。

    カプセルの量を見つけるためのJavaプログラム カプセルの量を見つけるためのJavaプログラム Feb 07, 2025 am 11:37 AM

    カプセルは3次元の幾何学的図形で、両端にシリンダーと半球で構成されています。カプセルの体積は、シリンダーの体積と両端に半球の体積を追加することで計算できます。このチュートリアルでは、さまざまな方法を使用して、Javaの特定のカプセルの体積を計算する方法について説明します。 カプセルボリュームフォーミュラ カプセルボリュームの式は次のとおりです。 カプセル体積=円筒形の体積2つの半球体積 で、 R:半球の半径。 H:シリンダーの高さ(半球を除く)。 例1 入力 RADIUS = 5ユニット 高さ= 10単位 出力 ボリューム= 1570.8立方ユニット 説明する 式を使用してボリュームを計算します。 ボリューム=π×R2×H(4

    未来を創る: まったくの初心者のための Java プログラミング 未来を創る: まったくの初心者のための Java プログラミング Oct 13, 2024 pm 01:32 PM

    Java は、初心者と経験豊富な開発者の両方が学習できる人気のあるプログラミング言語です。このチュートリアルは基本的な概念から始まり、高度なトピックに進みます。 Java Development Kit をインストールしたら、簡単な「Hello, World!」プログラムを作成してプログラミングを練習できます。コードを理解したら、コマンド プロンプトを使用してプログラムをコンパイルして実行すると、コンソールに「Hello, World!」と出力されます。 Java の学習はプログラミングの旅の始まりであり、習熟が深まるにつれて、より複雑なアプリケーションを作成できるようになります。

    See all articles