确定 Java 程序的确定性线程执行

发布于 2024-08-01 18:41:22 字数 4426 浏览 1 评论 0原文

我编写了一个非常简单的玩具程序,根据用户指定的计时要求完成线程内任务的执行。 代码和示例输出如下。 发生的情况是,每次运行代码时,任务完成时间都会在用户指定的时间的 + 增量范围内。 例如,如果用户想要在 5 秒内完成程序,根据代码运行的 CPU,它可能会在 5093 或 5012 毫秒内完成。 我想添加一些代码,这些代码可以自动确定特定 CPU 为特定版本的 JVM 提供的最低延迟。 基于该检测代码,可以将 delta 值添加到行中,例如: if (( taskRunTime > Patience+delta) && t.isAlive()) 以便系统带来更精确地执行任务计时。 请给一些建议。

代码:

public class ThreadExample 
{


    static void threadMessage(String message) 
    {
        String threadName = Thread.currentThread().getName();
        System.out.format("%s: %s%n", threadName, message);
    }

    private static class MessageLoop implements Runnable 
    {
        public void run() 
        {
            String importantInfo[] = 
            {
                "A new integrated approach to programming",
                "The innovative approach of the system",
                "The input of a tracking system",
                "A simulation system is then used for collision checking"
            };
            try 
                {
                    for (int i = 0; i < importantInfo.length; i++) 
                        {

                            Thread.sleep(4000);
                            threadMessage(importantInfo[i]);
                        }
                } 
                catch (InterruptedException e) 
                    {
                        threadMessage("I wasn't done!");
                    }
        }
    }

    public static void main(String args[]) throws InterruptedException 
    {


        //Delay, in milliseconds before we interrupt MessageLoop
        long patience = 1000 * 60 * 60;

        //If command line argument present, gives patience in seconds.
        if (args.length > 0) 
        {
            try {
                patience = Long.parseLong(args[0]) * 1000;
            } catch (NumberFormatException e) {
                System.err.println("Argument must be an integer.");
                System.exit(1);
            }

        }

        threadMessage("Starting MessageLoop thread");
        long startTime = System.currentTimeMillis(),taskRunTime=0;
        Thread t = new Thread(new MessageLoop());
        t.start();

        threadMessage("Waiting for MessageLoop thread to finish");
        //loop until MessageLoop thread exits
        while (t.isAlive()) 
        {
            threadMessage("Still waiting...");
            //Wait maximum of 1 second for MessageLoop thread to finish.
            t.join(100);
            taskRunTime=System.currentTimeMillis() - startTime;
            if (( taskRunTime > patience) && t.isAlive()) 
            {
                threadMessage("Tired of waiting...task is running longer than the patience you set or the default!");
                t.interrupt();
                t.join();
            }

        }
        threadMessage("Finally out of thread!");
        System.out.println("Time to complete task="+taskRunTime+"ms");

    }
}

Intel Centrino 1.7 Ghz 机器的示例输出(Java HotSpot(TM) 客户端 VM(版本 10.0-b23,混合模式))

java -jar ThreadExample.jar 5
main: Starting MessageLoop thread
main: Waiting for MessageLoop thread to finish
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
Thread-0: A new integrated approach to programming
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Tired of waiting...task is running longer than the patience you set or the default!
Thread-0: I wasn't done!
main: Finally out of thread!

I wrote a very simple toy program to complete the execution of a task inside a thread as per the timing requirements specified by a user. The code and the sample output is below. What happens is that everytime you run the code, the task completion times would be within a + delta range of the time specified by the user. For e.g if the user wants to complete the program in 5 secs it may complete in 5093 or 5012 ms according to the CPU the code runs on. I want to add in some code which can automatically determine the lowest latency that a particular CPU will provide for a particular version of the JVM. Based on that instrumentation code, a value of delta can be added to the line like : if (( taskRunTime > patience+delta) && t.isAlive()) so that the system brings in more precision to the task execution timing. Please give some suggestions.

Code:

public class ThreadExample 
{


    static void threadMessage(String message) 
    {
        String threadName = Thread.currentThread().getName();
        System.out.format("%s: %s%n", threadName, message);
    }

    private static class MessageLoop implements Runnable 
    {
        public void run() 
        {
            String importantInfo[] = 
            {
                "A new integrated approach to programming",
                "The innovative approach of the system",
                "The input of a tracking system",
                "A simulation system is then used for collision checking"
            };
            try 
                {
                    for (int i = 0; i < importantInfo.length; i++) 
                        {

                            Thread.sleep(4000);
                            threadMessage(importantInfo[i]);
                        }
                } 
                catch (InterruptedException e) 
                    {
                        threadMessage("I wasn't done!");
                    }
        }
    }

    public static void main(String args[]) throws InterruptedException 
    {


        //Delay, in milliseconds before we interrupt MessageLoop
        long patience = 1000 * 60 * 60;

        //If command line argument present, gives patience in seconds.
        if (args.length > 0) 
        {
            try {
                patience = Long.parseLong(args[0]) * 1000;
            } catch (NumberFormatException e) {
                System.err.println("Argument must be an integer.");
                System.exit(1);
            }

        }

        threadMessage("Starting MessageLoop thread");
        long startTime = System.currentTimeMillis(),taskRunTime=0;
        Thread t = new Thread(new MessageLoop());
        t.start();

        threadMessage("Waiting for MessageLoop thread to finish");
        //loop until MessageLoop thread exits
        while (t.isAlive()) 
        {
            threadMessage("Still waiting...");
            //Wait maximum of 1 second for MessageLoop thread to finish.
            t.join(100);
            taskRunTime=System.currentTimeMillis() - startTime;
            if (( taskRunTime > patience) && t.isAlive()) 
            {
                threadMessage("Tired of waiting...task is running longer than the patience you set or the default!");
                t.interrupt();
                t.join();
            }

        }
        threadMessage("Finally out of thread!");
        System.out.println("Time to complete task="+taskRunTime+"ms");

    }
}

Sample output from a Intel Centrino 1.7 Ghz machine ( Java HotSpot(TM) Client VM (build 10.0-b23, mixed mode) )

java -jar ThreadExample.jar 5
main: Starting MessageLoop thread
main: Waiting for MessageLoop thread to finish
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
Thread-0: A new integrated approach to programming
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Still waiting...
main: Tired of waiting...task is running longer than the patience you set or the default!
Thread-0: I wasn't done!
main: Finally out of thread!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

烧了回忆取暖 2024-08-08 18:41:22

我还写了一些关于 Thread.sleep 行为 和其他内容与线程和 Java 相关的可能有用的东西。

简而言之,您将获得的粒度取决于很多因素,其中一些因素是动态的。 按照您的建议进行检测是前进的一种方法。 您需要考虑的事项包括:

  • 给定条件下实际睡眠与请求的行为(请参阅我的文章,了解不同条件下的一些典型行为的说明)
  • 给定条件下的线程中断延迟(部分取决于 CPU 负载、调度策略)系统...)

此外,请考虑改进控制循环,以便它本质上(a)休眠所需的时间(在循环中,确保休眠时间),以及(b)在超时后中断线程。

顺便说一句,请始终使用 System.nanoTime() 进行计时。否则,您只会因为某些系统下 System.currentTimeMillis() 的粒度较差而造成混乱。

I've also written some stuff about the behaviour of Thread.sleep and other stuff related to threading and Java that might be of use.

The short answer is that the granularity you're going to get will depend on a lot of factors, some of which are dynamic. Instrumenting it as you suggest is one way forward. Things you need to think about instrumenting include:

  • behaviour of actual sleep vs requested under given conditions (see my article for an illustration of some typical behaviours under different conditions)
  • thread interrupt latency under given conditions (will depend partly on CPU load, scheduling policy of system...)

Also, consider improving the control loop so that it essentially (a) sleeps for the required time (in a loop, ensuring the time is slept for), and (b) interrupts the thread after the timeout.

BTW, always use System.nanoTime() for your timings. Otherwise, you're just confusing things because of the poor granularity of System.currentTimeMillis() under some systems.

无语# 2024-08-08 18:41:22

我建议您查看 Java Real Time: http://en.wikipedia.org/wiki/Real_time_Java
另请查看: http://java.sun .com/j2se/1.5.0/docs/guide/concurrency/overview.html

在 Java 1.5 之后,您不应该编写自己的线程

I would suggest you look in to Java Real Time: http://en.wikipedia.org/wiki/Real_time_Java
And also check out: http://java.sun.com/j2se/1.5.0/docs/guide/concurrency/overview.html

You shouldn't be writing you own threads after Java 1.5

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文