我的计时器的主题可能是用Thread.sleep作弊他?

时间:2012-12-18 17:13:09

标签: java multithreading

所以基本上我担心我的timertask的run方法在10分钟后没有被调用,因为我让主线程休眠10秒以避免疯狂的CPU使用只是通过一个空的while循环天。这是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...");
        }

    }
}

2 个答案:

答案 0 :(得分:4)

  

我担心我的timertask的run方法在10分钟后没有被调用,因为我正在让主线程休眠10秒

主线程中的Thread.sleep(...)不会影响Timer的运行。如果计时器在10分钟后没有运行,那么test.stop()是否可以阻止?

重要的是要意识到,如果测试在主线程中启动,然后在Timer线程中停止,则需要进行一些同步。我假设测试正在另一个线程中运行。您可能需要将其同步,然后在Timer线程中进行同步,您可以调用类似:

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

如果您不熟悉Java同步,则有一些good tutorials online

如果您想知道是否正在调用计时器,我会在您的计时器任务中设置一个断点,其中设置testDone = true并查看它是否到达那里。 这是一个good tutorial of using a debugger in eclipse

  

即使比较疯狂,while循环中的System.out也永远不会打印。我做了什么?

正如@assylias所提到的,while循环中的System.out(...)未显示,必须表示testDone设置为true。由于testDone正在更新并在不同的线程中访问,因此您需要确保它也是volatile


我刚刚运行了没有test.start()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;。您可能希望等待线程完成或其他什么。

  • 我不会将null ThreadGroup传递给Thread构造函数。只需使用不带ThreadGroup

  • 的构造函数

答案 1 :(得分:3)

我建议让testDone变得不稳定。实际上,我没有看到任何强制更改testDone的内容对于除了进行更改的线程之外的线程中的读取是可见的。