Skip to main content

TimeUnit rocks!

Posted by hallorant on October 21, 2011 at 1:10 PM PDT

The java.util.concurrent library added a little gem of a class, TimeUnit, which is well worth knowing a bit about. The class is used in java.util.concurrent to inform time-based methods how a given timing parameter should be interpreted. This class, however, can breathe readability back into an API that would otherwise be tough to eyeball.

Consider an example from the Timing Framework project.  In the API presented in the book Filthy Rich Clients (by Chet Haase and Romain Guy) you constructed an instance of an Animator as shown in the code snippet below:

animator = new Animator(10000, Animator.INFINITE, RepeatBehavior.LOOP);

This is a bit tough to understand without a bit of knowledge about the Animator constructor called. In fact, the first parameter is the time of the animation in milliseconds, the second parameter states that the animation should repeat forever (or until the animator is manually stopped), and the third parameter states that the animation should loop (the default repeat behavior is to reverse).

Today, using the current Timing Framework API, the snippet shown above would be changed to the code snippet below:

animator = new Animator.Builder()
  .setDuration(10000, TimeUnit.MILLISECONDS)
  .setRepeatCount(Animator.INFINITE)
  .setRepeatBehavior(RepeatBehavior.LOOP)
  .build();

My how things have changed!

First, the Builder pattern is used instead of (many) constructors. For more about this pattern (in Java) see Josh Bloch's Effective Java (second edition) Item 2: Consider a builder when faced with many constructor parameters. The use of the Builder helps to make it more obvious what each passed parameter is setting about the new Animator.

Second, the duration now has a value and units — we are using the TimeUnit class from java.util.concurrent to make it clear that value we are passing is intended to be a duration in milliseconds. Of course, now that we have TimeUnit we can write this duration a bit more clearly as 10 seconds, which most humans would intuit better than 10,000 milliseconds.

animator = new Animator.Builder()
  .setDuration(10, TimeUnit.SECONDS)
  .setRepeatCount(Animator.INFINITE)
  .setRepeatBehavior(RepeatBehavior.LOOP)
  .build();

This is great, if like me, you can change the API the library your using in your code (well, even I'm limited to only doing this for Timing Framework), but TimeUnit is so cool it can even help you out when the API doesn't use it. For example, I could use TimeUnit in the old TimingFramework API as shown below.

animator = new Animator(TimeUnit.MILLISECONDS.convert(10, TimeUnit.SECONDS), ...);

or

animator = new Animator(TimeUnit.SECONDS.toMillis(10), ...);

Here I'm using the built-in conversion abilities engineered into the TimeUnit class. The above two snippets are defined to be equivalent, so which one you prefer is up to you. Key here is that I get to use 10 seconds, which is the duration I'm thinking of, and the computer can convert this to what the API wants, a value in milliseconds. We avoid a human conversion which could be wrong.

TimeUnit really has helped calls to the Timing Framework API be easier to understand. It is also a great example of what can done with the enum type in the Java programming language. Finally, who wrote this little gem of a class? Doug Lea. Thanks Doug! (Update: Doug tells me that Tim Peierls also actively helped design TimeUnit. Thanks Tim!) TimeUnit is a cool little class that probably sould have been java.lang.TimeUnit — if only I could get that dang flux capacitor working in my DeLorean!

Related Topics >>