4

私はJavaとスレッドの世界に不慣れです..私は以下のようなサンプルコードを試していました:-

package com.alice.learnthread;

class NewThread implements Runnable{
Thread t;
long clicker=0;

private volatile boolean running=true;
NewThread(int p){
    t=new Thread(this);
    t.setPriority(p);
}
public void run(){
    while(running){
        clicker++;
    }
}
public void stop(){
    running=false;
}
public void start(){
    t.start();
}

}

 public class TestThread {
public static void main(String[] args){
    Thread r=Thread.currentThread();
    r.setPriority(Thread.MAX_PRIORITY);
    NewThread hi=new NewThread(Thread.NORM_PRIORITY+2);
    NewThread lo=new NewThread(Thread.NORM_PRIORITY-2);
    hi.start();
    lo.start();
    try{
        r.sleep(5000);
    }catch(InterruptedException e){
        System.out.println("caught");
    }
    hi.stop();
    lo.stop();
    try{
        hi.t.join();
        lo.t.join();
    }catch(InterruptedException e){
        System.out.println("cau1");
    }
    System.out.println("hi = "+hi.clicker+" lo="+lo.clicker);
}

}

ただし、本の出力によると、優先度の高いスレッドは変数クリッカーの値が高くなるはずです。しかし、私の場合、変数クリッカーの値は、優先度の高いスレッドよりも優先度の低いスレッドの方がはるかに高くなります。出力は次のようになります。

hi = 2198713135 lo=2484053552

これは、優先度の低いスレッドが優先度の高いスレッドよりも多くの CPU 時間を取得したという意味ではありません...何か不足していますか..ubuntu と win7 の両方で結果は同じです (優先度の低いスレッドのクリッカー値が高い)...

4

6 に答える 6

3

sulが言ったように、優先順位はJVMとの契約よりもヒントです。あなたの場合、あなたの結果はいくつかの理論によって説明することができます:

  • 2番目のスレッドは、最初のスレッドのコンパイルの利点を利用し、最初のスレッドの後で停止するため、より高速に実行されます。
  • whileループが揮発性変数の値をチェックするという事実は、jvmに値を実現させ、この間に他のスレッドにCPUを与える可能性があります。
  • stopメソッドは、スレッドを停止するのに多くの時間がかかります。

これは、スレッドの動作が予測できないという事実です。たとえば、最初に優先度の低いスレッドを開始してみてください。そうすれば、別の結果が得られると確信しています。

また、これを試してください:

public class TestThread
{
    public static void main(String[] args){
        Thread r=Thread.currentThread();
        r.setPriority(Thread.MAX_PRIORITY);
        NewThread hi=new NewThread(Thread.MAX_PRIORITY);
        NewThread lo=new NewThread(Thread.MIN_PRIORITY);
        hi.start();
        lo.start();
        try{
            r.sleep(5000);
        }catch(InterruptedException e){
            System.out.println("caught");
        }
        hi.interrupt();
        lo.interrupt();

        System.out.println("hi="+hi.clicker);
        System.out.println("lo="+lo.clicker);
    }
}
class NewThread extends Thread{
    long clicker=0;

    NewThread(int p){
        setPriority(p);
    }
    public void run(){
        while(true){
            clicker++;
        }
    }
}

揮発性変数を削除し、スレッドの停止方法を変更すると、別の結果が得られると確信しています。

于 2012-05-29T04:25:47.793 に答える
3

Java のスレッド優先度は、意図した動作を保証しません。これは、JVM へのヒントのようなものです。実際の動作は、基盤となる OS によって異なります。

また、Cooperative vs. Preemptive Threading についてのこの素敵なパラグラフを読んでください: http://www.cafeaulait.org/course/week11/32.html

于 2012-05-29T04:07:15.197 に答える
0

スレッドは本質的に予測不可能です。何らかの理由で優先度の高いスレッドが実行できない場合、優先度の低いスレッドが実行されます。さらに、すべてのスレッドが CPU をめぐって競合している場合、スレッドの優先度はあまり意味がありません。

しかし、上記のプログラムを実行すると、あなたの本で言及されているように、望ましい結果が得られました。

hi = 1707497920 lo=1699648942

hi = 1702682202 lo=1685457297
于 2012-05-29T04:20:27.407 に答える
0

Windows 7 で、スレッドの数を増やしてシステム リソースをめぐる実際の競合が発生し、実行時間増やすと、優先順位の高いスレッドが桁違いに多くのクリックを行うことがわかりました。そうでない場合は興味深いでしょう。あなたのテストケースは、競合する必要がある十分なリソースを使い果たすにはスレッド数が少なすぎ、JVM がネイティブスレッドにバインドするための実行時間も少なすぎると思います。

   public static void main(String[] args) {
        Thread r = Thread.currentThread();
        r.setPriority(Thread.MAX_PRIORITY);
        List<NewThread> hiThreads = new LinkedList<NewThread>();
        List<NewThread> lowThreads = new LinkedList<NewThread>();
        for (int i = 0; i < 10; i++) {
            NewThread hi = new NewThread(Thread.NORM_PRIORITY + 2);
            NewThread lo = new NewThread(Thread.NORM_PRIORITY - 2);
            hiThreads.add(hi);
            lowThreads.add(lo);
            hi.start();
            lo.start();
        }
        try {
            r.sleep(30000);
        } catch (InterruptedException e) {
            System.out.println("caught");
        }
        for (NewThread h : hiThreads) {
            h.stop();
        }
        for (NewThread l : lowThreads) {
            l.stop();
        }
        try {
            for (NewThread h : hiThreads) {
                h.t.join();
            }
            for (NewThread l : lowThreads) {
                l.t.join();
            }
        } catch (InterruptedException e) {
            System.out.println("cau1");
        }
        long hiClicker = 0l;
        for (NewThread h : hiThreads) {
            hiClicker += h.clicker;
        }
        long lowClicker = 0l;
        for (NewThread l : lowThreads) {
            lowClicker += l.clicker;
        }
        System.out.println("hi = " + hiClicker + " lo=" + lowClicker);
    }
于 2012-05-29T04:20:44.477 に答える
0

Java スレッドがどのように動作するかを確認するために、小さなアプリケーションを作成しました。

https://github.com/vinhqdang/java-thread-example

于 2014-11-27T10:35:37.603 に答える