5

JavaでTCPをシミュレートしたい。

そのために、すべての TCP 接続の送信側スレッドと受信側スレッドなど、複数のスレッドがあります。

私の問題は、(Thread.sleep() のように) スレッドをマイクロ秒間隔で一時停止したいということです。送信者スレッドが次のパケットを送信する前にマイクロ秒ブロックするフロー制御をシミュレートできるようにすると同時に、受信スレッドとデータ処理スレッドで CPU を使用できるようにします。しかし、マイクロ秒またはナノ秒の解像度で sleep() または wait() を実行するメソッドは見つかりませんでした。マイクロ秒またはナノ秒の解像度で Java のスレッドをブロック (一時停止) するにはどうすればよいですか?

System.nanoTime() メソッドを見つけましたが、指定されたマイクロ秒またはナノ秒の間スレッドをブロックするメソッドはありません。そのような方法があれば教えてください。System.nanoTime() は、相対的な時間間隔をナノ秒単位で与えるだけです。

System.nanoTime() を使用して、ビジー ループを使用するスレッドでナノ秒の遅延を実行できますが、これは CPU を浪費し、データ スレッドの受信またはスレッドの処理に使用できた可能性があります。

別の紛らわしい質問:

インターネットをサーフィンすることで、Windowsシステムで、スレッド割り込みなしで、少なくとも指定されたミリ秒または10ミリ秒の倍数のいずれか少ない方のThread.sleep()またはwait()メソッドブロックを見つけました。しかし、サンプルの例を実行すると、非常に異なる結果が見つかりました。同様のスレッドは、指定されたミリ秒未満でスリープしています。一部のスレッドで 100 マイクロ秒のスリープが発生しています。計測時間の誤差ですか?System.nanoTime() はそれほど正確ではありませんか? 非常に異なる結果が得られている以下の例を参照してください。スレッドの優先度も予測結果を示していません。

public class MyClass {
    public static void main(String args []){
        Runnable r = new Runnable() {
            public void run() {
                long s = System.nanoTime();
                //Thread.yield();  // Try for yield, need to check - in how much time high priority thread will be scheduled back after yielding
                try{
                    Thread.sleep(1);
                }catch(Exception e){

                }
                long e = System.nanoTime() - s;
                System.out.println(Thread.currentThread().getName()+e);
            }
        };

        Thread t1 = new Thread(r, "Thread T1: ");
        t1.setPriority(Thread.MAX_PRIORITY);
        t1.start();

        Thread t2 = new Thread(r, "Thread T2: ");
        t2.setPriority(Thread.MIN_PRIORITY);
        t2.start();

        Thread t3 = new Thread(r, "Thread T3: ");
        t3.setPriority(Thread.NORM_PRIORITY);
        t3.start();

        Thread t4 = new Thread(r, "Thread T4: ");
        t4.setPriority(Thread.MAX_PRIORITY);
        t4.start();

        long s = System.nanoTime();
        try{
            Thread.sleep(1);
        }catch(Exception e){

        }
        long e = System.nanoTime() - s;
        System.out.println("Main: "+e);
    }
}

Intel Core i5、2.53 GHz を搭載した私のシステムでは、複数の実行で以下のような出力が得られます。*以下の出力の改行はこの投稿には出力されません。コンソールから出力をコピーしましたが、コンソールに改行が表示されますが、問題ありません。

スレッド T1: 736682 スレッド T3: 700212 スレッド T2: 478559 メイン: 548257 スレッド T4: 458299

2 回目の実行 -

スレッド T3: 27555 スレッド T2: 139799 スレッド T1: 152361 メイン: 93199 スレッド T4: 29986

3 回目の実行 -

スレッド T4: 724525 スレッド T2: 1050319 メイン: 752486 スレッド T1: 941316 スレッド T3: 1000883

4 回目の実行 -

スレッド T1: 174243 スレッド T2: 166543 スレッド T3: 1005745 メイン: 1023170 スレッド T4: 915787

上記の実行では、マイクロ秒のブロッキングが発生しています。:O

これについて私を案内してください。

長文失礼します。投稿全体を読んでいただきありがとうございます。

4

4 に答える 4

4

は少なくともタイムアウト ミリ秒の間スリープすることをThread.sleep(timeout)保証しますが(基盤となるシステムの精度に依存します)、それより長くスリープする可能性があります。 Thread

ありますThread.sleep(millis, nanos)が、精度もあまり良くありません。@TimBender が以下で指摘しているように、OpenJDK 6-b14 では、丸めと呼び出しによってこれを実装していThread.sleep(millis)ます。そのため、どの Java 実装においても、正確な間隔でスリープすることを当てにすることはできないと言っても過言ではありません。

于 2012-10-29T20:58:53.007 に答える
3

あなたは OS スレッド スケジューラに翻弄されており、それについてはどうすることもできません。スリープ時間が非常に短いからといって、スリープが終了するとすぐにスケジューラがスレッドを目覚めさせるわけではありません。また、スレッドの優先度はヒントにすぎず、保証はありません。

于 2012-10-29T21:01:28.017 に答える
0

これを試して:

Thread.sleep(0, 250); // sleep 250 nanoseconds
于 2012-10-29T21:02:42.210 に答える
0

使用したいのはCondition.awaitNanosだと思いますが、これが要求された時間に近い高精度で返されることを実証する確固たる証拠は見つかりません。

または、必要な合計時間よりわずかに短い「awaitNanos」時間を渡し、合計時間が経過するまでループで「ライブ待機」することもできます。

于 2012-10-29T21:10:57.310 に答える