views:

181

answers:

2

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!
A: 

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

Pyrolistical
So you suggest the use of the concurrency utilities ? Where can i find examples of writing code that allow deterministic execution of concurrent tasks? In this particular simple case I'm not much bothered about task coordination and concurrency as I'm about determining determinism. Of course, the issue would come as soon as i've multiple tasks scheduled, but i want to start with simple things first.
iceman
+3  A: 

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.

Neil Coffey