从头认识多线程-4.3 ThreadLocal使用时需要注意的地方

Posted 李灵晖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从头认识多线程-4.3 ThreadLocal使用时需要注意的地方相关的知识,希望对你有一定的参考价值。

4.3 这一章节我们来讨论一下关于ThreadLocal的使用的时候需要注意的地方

ThreadLocal主要的使用是get、set、initialValue这几个方法,具体的使用我们这里不做介绍,下面只是举一些它使用的时候需要注意的地方。

1.在get方法的时候出现null

package com.ray.deepintothread.ch04.topic_3;

public class ThreadLocalGetNull {

    private int count = 0;

    public ThreadLocal<Integer> intThreadLocal = new ThreadLocal<Integer>();

    public int getCount() {
        return intThreadLocal.get();
    }

    public void addCount() {
        intThreadLocal.set(count++);
    }

    public static void main(String[] args) {
        System.out.println(new ThreadLocalGetNull().getCount());
    }
}

输出:
Exception in thread “main” java.lang.NullPointerException
at com.ray.deepintothread.ch04.topic_3.ThreadLocalGetNull.getCount(ThreadLocalGetNull.java:10)
at com.ray.deepintothread.ch04.topic_3.ThreadLocalGetNull.main(ThreadLocalGetNull.java:18)

这里直接抛空指针异常,为什么?因为ThreadLocal的实现是通过Map来实现的,我将会在后一章节介绍ThreadLocal的实现原理

对于上面的问题,我们的解决方案是:初始化的时候使用initialValue方法。

package com.ray.deepintothread.ch04.topic_3;

public class SolutionOfThreadLocalGetNull {

    private int count = 0;

    public ThreadLocal<Integer> intThreadLocal = new ThreadLocal<Integer>() {
        // 解决办法就是初始化数值
        @Override
        protected Integer initialValue() {
            return count;
        }
    };

    public int getCount() {
        return intThreadLocal.get();
    }

    public void addCount() {
        intThreadLocal.set(count++);
    }

    public static void main(String[] args) {
        System.out.println(new SolutionOfThreadLocalGetNull().getCount());
    }
}

输出:
0

在定义ThreadLocal之初就通过initialValue方法初始化返回的值。

2.ThreadLocal大部分的时间是使用在多线程的情况下,需要注意的是,每一个线程都只是使用ThreadLocal标注变量的副本进行计算

代码清单:(这里我沿用上一章节的例子)

package com.ray.deepintothread.ch04.topic_3;

public class ThreadLocalTest extends Thread {

    private int count = 0;

    public ThreadLocal<Integer> intThreadLocal = new ThreadLocal<Integer>() {
        protected Integer initialValue() {
            return count;
        };
    };

    public int getCount() {
        return intThreadLocal.get();
    }

    public void addCount() {
        intThreadLocal.set(count++);
    }

    @Override
    public void run() {
        try {
            for (int i = 0; i < 3; i++) {
                addCount();
                System.out.println("Thread[" + getName() + "] count[" + getCount() + "]");
                sleep(50);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        new ThreadLocalTest().start();
        Thread.sleep(100);
        new ThreadLocalTest().start();
        Thread.sleep(100);
        new ThreadLocalTest().start();
    }
}

输出:
Thread[Thread-0] count[0]
Thread[Thread-0] count[1]
Thread[Thread-1] count[0]
Thread[Thread-0] count[2]
Thread[Thread-1] count[1]
Thread[Thread-1] count[2]
Thread[Thread-2] count[0]
Thread[Thread-2] count[1]
Thread[Thread-2] count[2]

从输出我们可以看到,每一个线程操作的count的数值都是独立的,不被其他线程影响。

总结:这一章节我们讨论了ThreadLocal使用的两个注意的地方。

这一章节就到这里,谢谢


我的github:https://github.com/raylee2015/DeepIntoThread

目录:http://blog.csdn.net/raylee2007/article/details/51204573

以上是关于从头认识多线程-4.3 ThreadLocal使用时需要注意的地方的主要内容,如果未能解决你的问题,请参考以下文章

从头认识多线程-3.1 使用volatile解决异步死循环

从头认识java-18.6 synchronized在其他对象上同步和ThreadLocal来消除共享对象的同步问题

从头认识多线程-1.8 迫使线程停止的方法-暴力Stop方法

从头认识多线程-1.9 迫使线程停止的方法-return法

从头认识多线程-2.24 修改监视器对同步的影响

从头认识多线程-1.16 对照不同的优先级