Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a static Calendar thread safe

I'd like to use a Calendar for some static methods and use a static field:

private static Calendar calendar = Calendar.getInstance();

Now I read java.util.Calendar isn't thread safe. How can I make this thread safe (it should be static)?

like image 234
cody Avatar asked Jun 05 '11 18:06

cody


People also ask

Does static make thread safe?

A data type or static method is threadsafe if it behaves correctly when used from multiple threads, regardless of how those threads are executed, and without demanding additional coordination from the calling code.

Is calendar class thread safe?

In short, the Calendar class is not thread-safe, and GregorianCalendar isn't either because it inherits the non-thread-safe fields and methods.

Why java util Date is not thread safe?

util. Date is not thread safe, thus developers have to deal with concurrency issue while using date. The new date-time API is immutable and does not have setter methods. Poor design − Default Date starts from 1900, month starts from 1, and day starts from 0, so no uniformity.


3 Answers

Calendar is thread safe provided you don't change it. The usage in your example is fine.

It is worth noting that Calendar is not an efficient class and you should only use it for complex operations (like finding the next month/year) IMHO: If you do use it for complex operations, use local variables only.

If all you want it a snapshot of the time a faster way is to use currentTimeMillis which does even create an object. You can make the field volatile if you want to make it thread safe.

private static long now = System.currentTimeMillis();

The usage is a bit suspect. Why would you get the current time and store it globally like this. It reminds me of the old joke.

- Do you have the time?
- Yes, I have it written down somewhere.

like image 92
Peter Lawrey Avatar answered Oct 26 '22 15:10

Peter Lawrey


You can't make something thread-safe if it isn't. In the case of Calendar, even reading data from it isn't thread-safe, as it can update internal data structures.

If at all possible, I'd suggest using Joda Time instead:

  • Most of the types are immutable
  • The immutable types are thread-safe
  • It's a generally much better API anyway

If you absolutely have to use a Calendar, you could create a locking object and put all the access through a lock. For example:

private static final Calendar calendar = Calendar.getInstance();
private static final Object calendarLock = new Object();

public static int getYear()
{
    synchronized(calendarLock)
    {
        return calendar.get(Calendar.YEAR);
    }
}

// Ditto for other methods

It's pretty nasty though. You could have just one synchronized method which created a clone of the original calendar each time it was needed, of course... it's possible that by calling computeFields or computeTime you could make subsequent read-operations thread-safe, of course, but personally I'd be loathe to try it.

like image 33
Jon Skeet Avatar answered Oct 26 '22 15:10

Jon Skeet


You cannot. Yes, you could synchronize on it, but it still has mutable state fields. You'll have to create your own Calendar object.

If possible, use something lightweight, like a long measuring the times in milliseconds, and only convert to a Calendar when you NEED to.

like image 30
MJB Avatar answered Oct 26 '22 16:10

MJB