Date Conversion with ThreadLocal
Asked Answered
I

3

9

I have a requirement to convert incoming date string format "20130212" (YYYYMMDD) to 12/02/2013 (DD/MM/YYYY)

using ThreadLocal. I know a way to do this without the ThreadLocal. Can anyone help me?

Conversion without ThreadLocal:

    final SimpleDateFormat format2 = new SimpleDateFormat("MM/dd/yyyy");
    final SimpleDateFormat format1 = new SimpleDateFormat("yyyyMMdd");
    final Date date = format1.parse(tradeDate);
    final Date formattedDate = format2.parse(format2.format(date));
Ingathering answered 3/9, 2013 at 10:31 Comment(2)
Why do you need to use a ThreadLocal?Kronstadt
Because SimpleDateFormats (and indeed most other Format instances) are not thread-safe. See my blog post on this topic.Variometer
Y
11

ThreadLocal in Java is a way to achieve thread-safety apart from writing immutable classes. Since SimpleDateFormat is not thread safe, you can use a ThreadLocal to make it thread safe.

class DateFormatter{

    private static ThreadLocal<SimpleDateFormat> outDateFormatHolder = new ThreadLocal<SimpleDateFormat>() {
    @Override
    protected SimpleDateFormat initialValue() {
        return new SimpleDateFormat("MM/dd/yyyy");
    }
};

private static ThreadLocal<SimpleDateFormat> inDateFormatHolder = new ThreadLocal<SimpleDateFormat>() {
    @Override
    protected SimpleDateFormat initialValue() {
        return new SimpleDateFormat("yyyyMMdd");
    }
};

public static String formatDate(String date) throws ParseException { 
    return outDateFormatHolder.get().format(
            inDateFormatHolder.get().parse(date));
}        
}
Yorgen answered 3/9, 2013 at 10:59 Comment(5)
Thanks Richie, But your class not working saying class body,field declaration not completed.i added extra closing braces but still no luck.and also how to remove these threadlocal references once calll is over.Ingathering
check now. I have added the braces now.Yorgen
otherwise it will leak the memory .why do we want these references after the current thread work has done.Ingathering
If you see the code - both the objects are static which means that it would be like singleton. As long as you are not creating ThreadLocal instances each time, you need not worry about memory leaks. But in case you are very particular - to remove references, you can manually call outDateFormatHolder.remove() and inDateFormatHolder.remove() from formatDate method. #3869526Yorgen
"final Date date = format1.parse(tradeDate); final Date formattedDate = format2.parse(format2.format(date));" - date and formattedDate are the same - You can debug and check. If you need the date object then the first statement is enough - the date object is not stored with the format. If you want to print the date object again after your second statment, still you will need to call the format method.Yorgen
P
14

The idea behind this is that SimpleDateFormat is not thread-safe so in a mutil-threaded app you cannot share an instance of SimpleDateFormat between multiple threads. But since creation of SimpleDateFormat is an expensive operation we can use a ThreadLocal as workaround

static ThreadLocal<SimpleDateFormat> format1 = new ThreadLocal<SimpleDateFormat>() {
    @Override
    protected SimpleDateFormat initialValue() {
        return new SimpleDateFormat("yyyy-MM-dd");
    }
};

public String formatDate(Date date) {
    return format1.get().format(date);
}
Pending answered 3/9, 2013 at 10:39 Comment(4)
Do people do that? If you (the original l poster) does not understand ThreadLocals properly I would recommend not using them. I would maybe consider FastDateFormat from Commons Lang, or DateTimeFormat from the JodaTime library. Here is a long and interesting thread on the subject.. jsr166-concurrency.10961.n7.nabble.com/…Kronstadt
@Kronstadt : Yes, people do that. I also recommend it. How is he not understanding ThreadLocals properly? Joshua Bloch, author of Effective Java says on your link: "This thread is littered with misinformation. [..] There is nothing inherently wrong with thread locals: They do not cause memory leaks. They are not slow.". The discussion is about bugs in Tomcat and some other apps that use thread pools and have implementation issues with ThreadLocals. They can and should be fixed in those apps.Variometer
@StijndeWitt Because his question is [paraphrased] "I do not know how to do this using Thread Local". See also, "otherwise it will leak the memory .why do we want these references after the current thread work has done", which shows a lack of understanding. Agree should be fixed in the containers, but you firstly need to understand what they are and secondly how they might impact your project is you use them incorrectly. Or, just copy a code snippet from SO and don't worry about understanding what it does.Kronstadt
True... I was confused by the comment being on this answer and not on the question itself but you are right... Only use something if you understand the effects it will have.Variometer
Y
11

ThreadLocal in Java is a way to achieve thread-safety apart from writing immutable classes. Since SimpleDateFormat is not thread safe, you can use a ThreadLocal to make it thread safe.

class DateFormatter{

    private static ThreadLocal<SimpleDateFormat> outDateFormatHolder = new ThreadLocal<SimpleDateFormat>() {
    @Override
    protected SimpleDateFormat initialValue() {
        return new SimpleDateFormat("MM/dd/yyyy");
    }
};

private static ThreadLocal<SimpleDateFormat> inDateFormatHolder = new ThreadLocal<SimpleDateFormat>() {
    @Override
    protected SimpleDateFormat initialValue() {
        return new SimpleDateFormat("yyyyMMdd");
    }
};

public static String formatDate(String date) throws ParseException { 
    return outDateFormatHolder.get().format(
            inDateFormatHolder.get().parse(date));
}        
}
Yorgen answered 3/9, 2013 at 10:59 Comment(5)
Thanks Richie, But your class not working saying class body,field declaration not completed.i added extra closing braces but still no luck.and also how to remove these threadlocal references once calll is over.Ingathering
check now. I have added the braces now.Yorgen
otherwise it will leak the memory .why do we want these references after the current thread work has done.Ingathering
If you see the code - both the objects are static which means that it would be like singleton. As long as you are not creating ThreadLocal instances each time, you need not worry about memory leaks. But in case you are very particular - to remove references, you can manually call outDateFormatHolder.remove() and inDateFormatHolder.remove() from formatDate method. #3869526Yorgen
"final Date date = format1.parse(tradeDate); final Date formattedDate = format2.parse(format2.format(date));" - date and formattedDate are the same - You can debug and check. If you need the date object then the first statement is enough - the date object is not stored with the format. If you want to print the date object again after your second statment, still you will need to call the format method.Yorgen
Y
1

Java-8+

The modern Date-Time classes introduced with Java-8 are thread-safe.

Demo:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter parser = DateTimeFormatter.ofPattern("uuuuMMdd", Locale.ENGLISH);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/uuuu", Locale.ENGLISH);
        LocalDate date = LocalDate.parse("20130212", parser);
        String formattedString = date.format(formatter);
        System.out.println(formattedString);
    }
}

Output:

12/02/2013

Note that I prefer u to y with DateTimeFormatter.

Learn more about the modern Date-Time API from Trail: Date Time.

You answered 17/10, 2022 at 17:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.