Threadlocal memory leak

I see that someone said: "When you want to use ThreadLocal in your class, use it in a static way", for example:

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

I am not sure why this can avoid a memory leak. Can someone give some clarification?

+1
source share
2 answers

I encoded some PoC and ran jvisualvmto actually show if static is ThreadLocalanything other than an instance ThreadLocal.
The code starts 10 different threads, each of which starts a hundred millionth loop that uses the object SimpleDateFormatstored in the field ThreadLocal.

Static ThreadLocal

public class Main {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + " " + dayFormat.get().format(new Date()));
                for (int j = 0; j < 100000000; j++) {
                    dayFormat.get().format(new Date());
                }
                System.out.println(Thread.currentThread().getName()+" "+dayFormat.get().format(new Date()));
            }).start();
        }
    }

    private static ThreadLocal<SimpleDateFormat> dayFormat =
            new ThreadLocal<SimpleDateFormat>() {
                protected SimpleDateFormat initialValue() {
                    return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                }
            };
}

static not null

There are no memory leaks, as expected.

Instance ThreadLocal

public class Main {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                Main m = new Main();
                System.out.println(Thread.currentThread().getName() + " " + m.dayFormat.get().format(new Date()));
                for (int j = 0; j < 100000000; j++) {
                    m.dayFormat.get().format(new Date());
                }
                System.out.println(Thread.currentThread().getName()+" "+m.dayFormat.get().format(new Date()));
            }).start();
        }
    }

    private ThreadLocal<SimpleDateFormat> dayFormat =
            new ThreadLocal<SimpleDateFormat>() {
                protected SimpleDateFormat initialValue() {
                    return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                }
            };
}

instance, not null

. ( 20%) , , .

, "" ThreadLocal , , GC .
.

ThreadLocal,

public class Main {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + " " + dayFormat.get().format(new Date()));
                for (int j = 0; j < 100000000; j++) {
                    dayFormat.set(null);
                    dayFormat.set(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
                    dayFormat.get().format(new Date());
                }
                System.out.println(Thread.currentThread().getName()+" "+dayFormat.get().format(new Date()));
            }).start();
        }
    }

    private static ThreadLocal<SimpleDateFormat> dayFormat =
            new ThreadLocal<SimpleDateFormat>() {
                protected SimpleDateFormat initialValue() {
                    return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                }
            };
}

static, nullified

ThreadLocal,

public class Main {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                Main m = new Main();
                System.out.println(Thread.currentThread().getName() + " " + m.dayFormat.get().format(new Date()));
                for (int j = 0; j < 100000000; j++) {
                    m.dayFormat.set(null);
                    m.dayFormat.set(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
                    m.dayFormat.get().format(new Date());
                }
                System.out.println(Thread.currentThread().getName()+" "+m.dayFormat.get().format(new Date()));
            }).start();
        }
    }

    private ThreadLocal<SimpleDateFormat> dayFormat =
            new ThreadLocal<SimpleDateFormat>() {
                protected SimpleDateFormat initialValue() {
                    return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                }
            };
}

instance canceled

. - GC, "" , , .
, ( 5%) .

, , , , , , ThreadLocal .

+2

. , "" usecase , threadlocal , , , .

, threadlocal , .

, ( , , , , threadlocals ), , .

+1

Source: https://habr.com/ru/post/1676666/


All Articles