Java Singletons don’t exist.

*** Posted on https://bigendian.wordpress.com All rights reserved ***

When I first started in my current project I set down to a code review with the lead programmer to see “my” project. At some point during the review, the man pointed to a certain class that was being used as part of the startup sequence for the application and said “this should be reimplemented as a singelton”. Up until then I was following him closely, but that statement took me by surprise, because as far as I knew, singletons don’t exist in Java.

To understand why, we have to look at the definition of a Singelton:

A singleton is a pattern that permits exactly one object that is needed to coordinate actions across the system.

In other words, whereever I am, if I try to use a class that is defined as a singleton, I would always, always, get the SAME object.  Usually, a native implementation of a Singleton looks something like this:

public final class MySingleton{

private MySingelton me=null;

private MySingleton(){
   ...instantiation code here...
}

public Mysingelton getInstance(){
  if (null==me) me = new MySingelton();
  return me;
}

}

As you can see, MySingleton has no public contractors. It can’t be directly instantiated or inherited. You can only get a MySingleton Object by calling getInstance(), which always returns the same object. This makes the singleton very handy for coordinating actions across a system. System states, for example, can be saved as singletons, as can factories, shared queues (a synchronized singleton), thread states, etc. Everywhere in the system that you can the singleton’s name, you’re guarantied to have the exact same object returned to you.

So why are there no Java singletons? Clearly the code above is written in Java and would run in Java, and would function as expected in a Java program. The reason this is not a singleton is the last part of the singleton definition “across the system”.

Consider: In C++, I can use code very much like the one above to tell me if a program has been launched. On the first time that the program runs, it asks for the singleton object, gets it (after it has been allocated by the system) and modifies it to indicate that it had been launched. If the program is then launched again, the second instance of the program would request and get the SAME singleton, see that the “running” state has already been set, and exit. The singleton is used across the system in coordinate states.

In Java, on the other hand, every program instance would run in its own instance of the JVM. This means that when the second instance of the program is launched, it would NOT get the same object as the first instance, but rather it would get the instance that has just been instantiated in its own JVM. The code above can coordinate across the same JVM, but it fails to coordinate across the system. Therefore, it does not qualify as a true singleton.

This may seem like splitting hairs, but it’s a very important thing to know. The guy I set with in the code review was pointing at a class who’s job was to make sure only one instance of the application would ever launch. We work on a project that does network measurements and topographies. It sends out packets with different addresses and TTLs and uses the returns to map the Internet. If we have two instances of the application running at the same time, we may not know which packet was sent by which instance, and our results would be compromised. Furthermore: We allow our users to run the application as a service, or as a standalone GUI based program. If we don’t have mutual exclusion, we can run into a situation where a user had installed the service AND the GUI, and starts both, thinking that the GUI just reflects the service. This could very easily lead to corruption in our data, and problems in the whole research.  All because Java singletons aren’t really singletons.

The good news is that in 95% of the cases, the code above would work quite nicely as a singleton. So long as you are staying within the JVM, it’s fine. For the last 5%, there are workarounds that can make mutual exclusion possible in Java. I will post about that some other time, though.

Good Coding,

B.E.

Advertisements

Java Thread Priority – The Awful Truth!

Ok, ok, I admit I might have been watching a little too much E!® channel lately, and the threading system in Java isn’t that awful. But if you will, let’s try a little exercise:

First of all, an easy question: What’s the default priority for a newly created Java thread? (Hint: it’s listed as NORM_PRIORITY here.)

For anyone who answered “5” (with or without looking) congratulations! You’re right. There are 10  internal levels of priority in Java, and 5 is considered the “normal” priority, and the default for new threads.

Now lets do a little mind experiment: Lets say you write a program that does some calculation and displays the result to a swing GUI. Your program gets its input automatically, and it can start calculating as soon as it starts up, so the first thing you do in your main(args[]) is to spawn a calculation thread to do the work. It gets a priority of 5, as we said. Great so far.

Now, on your GUI you are beginning to get results from your calculations. But they’re not coming as quickly as you need them. It’s just that the calculations are really I/O bound, and it takes a long time to get them, so that your calculation thread (and your CPU) spend a lot of time waiting idle. You decide to help the situation a long a bit by pressing the button on the GUI that would spawn a second calculation thread. Same code, same class, same parameters.

OK. Pop quiz, hot shot: What’s the priority of the second calculation thread?

If you answered 5 again, you’d be wrong. The new thread has a priority of 6. Don’t believe me? Try it.

What’s happened? How did identical threads end up with different priorities?

The answer is that, while it is true that the “default” priority for a Java thread is 5, that’s just about meaningless because A Java thread inherits the priority of its parent thread. In this particular case, the thread that created the second thread was the EventDispatcher thread, which is responsible for handling GUI tasks. Since it’s generally desired that a GUI be responsive no matter what the application is doing, this thread was given a default priority that is a little higher then the rest: 6. This is all fine and well, except that every thread that is created via this thread also has that priority. This can lead to a situation where practically all threads are running in this “elevated” priority, which not only defeats the purpose of of setting that thread higher, but can actually cause execution problems.

I’ll give an example: I’ve had a task recently to move our program’s system tray icon implementation from a 3rd party jar to the newfangled Java 6 built-in implementation. In my coded I spawned a thread to deal with the action events that come from the system tray, and like a good boy (who’s aware of how Java thread priority actually works) I manually set the priority of the thread to Thread.NORM_PRIORITY, where it should be. The results were incredible: from an average shut-down of 1-3 seconds, the program began taking up to several MINUTES to shutdown. Taking out the setPriority line fixed the problem, but exposed a different one: The previous programmers who had worked on this program didn’t realize that the priority is inherited, and let it as is. This meant that practically EVERY thread was running with priority 6 EXCEPT mine. The program took so long to shutdown because the thread that was suppose to tell all the other ends to stop couldn’t get a word in edgewise! Oooops. (not a good word to hear about your code)

The actual truth is not quite that terrible as I make it sound. Most preemptive, time-slicing Operating systems (Like Windows® and Linux) wont let a thread completely starve, and will temporarily assign a higher priority to a low thread that hasn’t ran in a while. As I understand it, there was also some re-shuffling in the way Java 6 maps internal priorities to Windows priorities that makes priority 5 and 6 virtually identical (Although I would point out that the example above was on a Java 6 JVM running on Vista®) But still, this is something of which anyone who write GUI code must be aware.

B.E.