2

所以本质上我担心我的 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...");
        }

    }
}
4

2 回答 2

4

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

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

重要的是要认识到,如果测试是在主线程中开始的,然后在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. ++ 不是原子操作,因此即使该字段是易失的,多个线程也可以覆盖彼此的增量。

  • If you are trying to wait for the threads to complete, instead of sleeping for 10 minutes, I'd recommend calling thread[i].join() with the threads. Even better would be use an ExecutorService and use the awaitTermination(...) method.

  • You call shouldStop = true; and then return the completedSynths;. You may want to wait for the threads to finish or something.

  • I'd not pass in a null ThreadGroup to the Thread constructor. Just use the constructor without the ThreadGroup.

于 2012-12-18T17:23:05.900 回答
3

I suggest making testDone volatile. As it is, I don't see anything forcing changes to testDone to be visible to reads in threads other than the one making the change.

于 2012-12-18T17:28:07.370 回答