ホームページ  >  記事  >  Java  >  Java で一般的に使用される 4 つのスレッド関数は何ですか?

Java で一般的に使用される 4 つのスレッド関数は何ですか?

WBOY
WBOY転載
2023-04-26 14:01:071328ブラウズ

1. wait()

現在のスレッドは、通常は通知や割り込みによって起動されるまで、または特定のリアルタイム時間が経過するまで待機します。

自体は Object クラスに属しています。ソース コードからわかります: public class Object {

ソース コードを見ると、3 つのオーバーロードされたメソッドがあることがわかります。詳細なソースコードは次のとおりです:

//第一个重载函数
public final void wait() throws InterruptedException {
        wait(0L);
    }
    
//第二个重载函数
public final native void wait(long timeoutMillis) throws InterruptedException;


//第三个重载函数
public final void wait(long timeoutMillis, int nanos) throws InterruptedException {
        if (timeoutMillis < 0) {
            throw new IllegalArgumentException("timeoutMillis value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos > 0 && timeoutMillis < Long.MAX_VALUE) {
            timeoutMillis++;
        }

        wait(timeoutMillis);
    }

具体的な実際の呼び出しコードは次のとおりです:

wait 関数が実行されると、この 4 秒以内にロックが解放され、スレッドが一時停止されます。 。この 4 秒以内に Notice() に協力できれば目覚めてロックを取得できますが、目覚めない場合は他の人が競合するまで待ちます。デフォルトでは 4 秒後、ロックは自動的に解放されます。

現在のスレッドが Thread.wait() を待機している間、スレッドが終了すると、自動的に起動してロックを自動的に解放します。

@Override
public void run() {
       synchronized (a) {
           a.wait(4000);      
       }
}

2 . join()

join は Thread クラスのメソッドです。

具体的なソース コードは次のとおりです。オーバーロードされた 3 つのメソッド

//第一个重载函数
public final synchronized void join(final long millis)
    throws InterruptedException {
        if (millis > 0) {
            if (isAlive()) {
                final long startTime = System.nanoTime();
                long delay = millis;
                do {
                    wait(delay);
                } while (isAlive() && (delay = millis -
                        TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime)) > 0);
            }
        } else if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            throw new IllegalArgumentException("timeout value is negative");
        }
    }


//第二个重载函数
/*等待该线程死亡的时间最多为毫秒加纳秒。 如果两个参数都为0,则意味着永远等待。  
这个实现使用了This的循环。 等待电话以this.isAlive为条件。 当一个线程终止this。 
调用notifyAll方法。 建议应用程序不要使用wait、notify或notifyAll on Thread实例。  */
public final synchronized void join(long millis, int nanos)
throws InterruptedException {

    if (millis < 0) {
        throw new IllegalArgumentException("timeout value is negative");
    }

    if (nanos < 0 || nanos > 999999) {
        throw new IllegalArgumentException(
                            "nanosecond timeout value out of range");
    }

    if (nanos > 0 && millis < Long.MAX_VALUE) {
        millis++;
    }

    join(millis);
}


//第三个重载函数
/*等待线程死亡。  
此方法的调用与调用的行为完全相同  

InterruptedException—如果任何线程中断了当前线程。 当抛出此异常时,当前线程的中断状态将被清除。  */
public final void join() throws InterruptedException {
     join(0);
 }

主な時間パラメータのロジックは次のとおりです:

  • が 0 未満の場合、例外がスローされます。

  • が 0 に等しい場合、join( A) は、A が存在するかどうかを判断し、存在する場合にのみ操作を実行します。このスレッドは wait(0) を実行し、スレッド A の実行が完了するまで待機します。

  • は 0 より大きく、wait(long millis) を実行することを除いて上記と同じです。待機時間が終了したため、操作の実行を続行する前に

3. sleep()

前の待機関数を比較してください

  • sleep(long mills) : CPU リソースを放棄しますが、ロック リソースは解放しません。

  • wait(): CPU リソースを放棄し、リソースをロックします。

#sleep 関数のソース コードを見ると、オーバーロードされた関数が 2 つあります。

どちらも Thread クラスの関数です。

/*根据系统计时器和调度器的精度和准确性,
使当前执行的线程在指定的毫秒数内处于睡眠状态(暂时停止执行)。 
线程不会失去任何监视器的所有权。*/
public static native void sleep(long millis) throws InterruptedException;



/*导致当前执行的线程在指定的毫秒数加上指定的纳秒数
(取决于系统计时器和调度器的精度和准确性)内休眠(暂时停止执行)。 
线程不会失去任何监视器的所有权。  */
public static void sleep(long millis, int nanos)
    throws InterruptedException {
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos > 0 && millis < Long.MAX_VALUE) {
            millis++;
        }

        sleep(millis);
    }

4. yield ()

yield() 関数のソース コードを見てください。オーバーロードされた関数

は Thread クラスの関数です。

は、現在のスレッドはプロセッサの現在の使用を放棄するつもりです。スケジューラはこのプロンプトを無視できます。

Yield は、CPU を過剰に使用してしまうスレッド間の相対的なプロセスを改善するためのヒューリスティックな試みです。実際に意図した効果があることを確認するには、詳細な分析とベンチマークを組み合わせて使用​​する必要があります。

この方法の使用が適切であることはほとんどありません。これは、競合状態によるエラーの再現に役立つ可能性があるデバッグまたはテストの目的で使用される場合があります。また、java.util.concurrent.locks パッケージ内のような同時実行制御構造を設計するときにも役立つ場合があります。

public static native void yield();

一般に、yield 関数の主な機能は次のとおりです。

CPU スケジューリングを放棄し、スレッドを一時停止しますが、時間をユーザーが指定することはできません

同じ優先度を与えることができる レベルに実行機会がある

5. 概要

wait はスレッドを一時停止し、CPU を放棄し、ロックを解放します。 (オブジェクト クラス)

join はスレッドを一時停止し、スレッドの実行後に独自のスレッドに戻ることができます。 (スレッドクラス)

sleep ロックを解放せずにスレッドを一時停止し、CPU を放棄します。 (スレッドクラス)

yield はスレッドを一時停止しますが、ユーザーが指定することはできず、同じ優先順位に実行の機会を与えることしかできません。 (スレッドクラス)

5.1 wait と join の違い

上記のソース コードとロジック コードを読んだ後、この 2 つの類似点と相違点について話しましょう

一般

  • wait 関数: 現在のスレッドを待機状態にします。wait() は、notify() および NoticeAll() メソッドと一緒に使用されます。通知はウェイクアップ関数

  • #join 関数です。独自のスレッドを実行する前に、このスレッドが終了するのを待ちます。その主な機能は同期であり、スレッド間の実行を「並列」から「直列」に変更します。スレッド B の join() メソッドがスレッド A で呼び出されると、スレッド

の実行プロセスが変更されます。スレッド A は、実行を続行する前に、スレッド B の実行が完了するまで待機する必要があります

共通点:

    #現在のスレッドを一時停止
  • #割り込みによって起動可能
  • #違いは次のとおりです:

違いwaitオブジェクトクラススレッド間通信同期する必要がありますwait(): CPU リソースを放棄し、リソースをロックします。
参加 クラス
スレッドクラス 目的
並べ替えてみようシリアルに渡す 同期
同期せずに使用できます #5.2 wait と sleep の違い
sleep(long mills): CPU リソースを放棄しますが、ロック リソースは解放しません。

違いは主に CPU の動作メカニズムに依存します。

違いは主に 2 つの点です。1. CPU が実行を継続するかどうか、2. ロックが解放されるかどうか。

最終分析:

wait、notify、notifyall はすべて Object オブジェクトのメソッドであり、これらは一緒に使用され、ロック機構に使用されるため、ロックが解放されます。

そしてスリープは、Thread クラスはロックとは何の関係もなく、ロックを解放しません

しかし、両方とも CPU リソースを放棄します

以上がJava で一般的に使用される 4 つのスレッド関数は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。