2

したがって、基本的には、timertask のrunメソッドが 10 分後に呼び出されないことが懸念されます。これは、メイン スレッドを 10 秒間スリープ状態にして、空の while ループを 1 日中実行するというクレイジーな CPU 使用率を避けるためです。Java main メソッドのコードは次のとおりです。

 private static boolean testDone = false;
 public static void main(String[] args)
 {
        final int minutes = 10;
        final StressTest test = new StressTest(someParams);

        test.start();

        Timer timer = new Timer();
        timer.schedule(new TimerTask(){

            @Override
            public void run() {

                testDone = true;
                int completedSynths = test.stop();
                System.out.println("Completed Synths: " + completedSynths);
                System.out.println("Elapsed Time in Minutes: " + minutes);
                System.out.println("Throughput (synths/min): " + completedSynths/minutes);

            }}, minutes*60*1000);

        while(!testDone)
        {
            System.out.println("Still not done... sleeping for 10 secs....");
            Thread.sleep(10000);
        }

        System.exit(0);

さらにクレイジーなことに、インザSystem.outループwhileは決して印刷されません。私が何をした??

編集: StressTest オブジェクトの疑似コードを追加するには

public class StressTest 
{

    private SecureRandom random = new SecureRandom();

    private volatile int completedSynths = 0;

    private volatile boolean shouldStop = false;

    private Thread[] threads;

    /**
     * Instantiate a new StressTest object.
     * 
     * @param threadCount number of concurrent threads to be polling server
     */
    public StressTest(int threadCount)
    {
        threads = new Thread[threadCount];
    }

    public void start()
    {
        System.out.println("Starting Stress Test....");

        for(int i = 0; i < threads.length; i++)
        {
            Runnable synthCaller = new SynthApiCaller();
            threads[i] = new Thread(null, synthCaller, "SynthThread" + i);
            threads[i].run();
        }
    }

    public int stop()
    {
        System.out.println("Stopping Stress Test...");
        shouldStop = true;

        return completedSynths;
    }

    private String randId()
    {
        return new BigInteger(130, random).toString(32);
    }

    private class SynthApiCaller implements Runnable
    {
        @Override
        public void run() 
        {
            while(!shouldStop)
            {
                try 
                {
                            //this class makes an HTTP request to a server and then writes result to a file
                    MyClass.writeFile( "someFileLoc/file.data");
                    completedSynths++;

                    Runtime.getRuntime().exec("rm -r " + fileLoc);
                    System.out.println("Synth # " + completedSynths);
                } 
                catch (IOException e) 
                {
                    System.out.println(e.getMessage());
                }
            }

            System.out.println("Thread terminated...");
        }

    }
}
4

2 に答える 2

4

メイン スレッドを 10 秒間スリープ状態にしているため、timertask の run メソッドが 10 分後に呼び出されないことが懸念されます。

メイン スレッドのThread.sleep(...)は、 の実行には影響しませんTimertest.stop()タイマーが 10 分経過しても動作しない場合、ブロックされている可能性はありますか?

テストがメイン スレッドで開始され、スレッドで停止されている場合はTimer、何らかの同期が必要になることを認識することが重要です。テストは別のスレッドで実行されていると思います。おそらく同期する必要があり、Timerスレッド内で次のように呼び出します。

synchronized (test) {
    test.start();
}

Java 同期を初めて使用する場合は、オンライン に優れたチュートリアルがいくつかあります。

タイマーがまったく呼び出されているかどうか疑問に思っている場合は、タイマー タスク内にブレーク ポイントを設定し、そこに到達するかどうかを確認testDone = trueします。これは、Eclipse でデバッガーを使用するための優れたチュートリアルです

さらにクレイジーなことに、while ループの System.out は決して印刷されません。私が何をした??

@assyliasが述べたように、System.out(...)whileループが表示されないということ は、それtestDoneがtrueに設定されていることを意味する必要があります。は別のスレッドで更新およびアクセスされるためtestDone、それも であることを確認する必要がありvolatileます。


test.start()andなしでコード サンプルを実行したところ、stop()問題なく動作するようです。問題はtestコードにある可能性があります。

Still not done... sleeping for 10 secs....
Still not done... sleeping for 10 secs....
...
Completed Synths: 1
Elapsed Time in Minutes: 10
Throughput (synths/min): 0

コードを追加したので、コメントをいくつか示します。

  • completedSynths++;に変更する必要がありAtomicIntegerます。++ はアトミック操作ではないため、フィールドが揮発性であっても、複数のスレッドが互いのインクリメントを上書きできます。

  • スレッドが完了するまで待機する場合は、10 分間スリープするのではなく、thread[i].join()スレッドで呼び出すことをお勧めします。さらに良いのは、メソッドExecutorServiceを使用してawaitTermination(...)メソッドを使用することです。

  • を呼び出しshouldStop = true;てから、 を返しますcompletedSynths;。スレッドが終了するか何かを待つことができます。

  • コンストラクターに anull ThreadGroupを渡しません。Threadなしでコンストラクターを使用するだけThreadGroupです。

于 2012-12-18T17:23:05.900 に答える
3

testDone を volatile にすることをお勧めします。現状では、testDone への変更を、変更を行ったスレッド以外のスレッドの読み取りに表示するように強制するものは何もありません。

于 2012-12-18T17:28:07.370 に答える