从头认识多线程-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

时间: 2024-10-05 21:11:08

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

SQL 中 Null 值使用时需要注意的地方

一.Null不支持大小/相等判断 1.下面的2个查询,不管表 users 中有多少条记录,返回的记录都是0行 select * from  users where deleted_at = null; select * from  users where deleted_at != null; 用常规的比较操作符(normal conditional operators)来将 null 与其他值比较是没有意义的. Null 也不等于 Null 2.将某个值与 null 进行比较的正确方法是使用

time.h文件中包含的几个函数使用时须注意事项

time.h头文件中包含以下函数 char* asctime(const struct tm *tm); char* asctime_r(const struct tm *tm,char *buf); char* ctime(const time_t *timep); char* ctime_r(const time_t *timep,char *buf); struct tm *gmtime(const time_t *timep); struct tm *gmtime_r(const tim

EntityFrameWork 使用时碰到的小问题

EntityFrameWork 使用时碰到的小问题 1,在使用orm访问数据库的相目里,也要引用EntityFrameWork.dll,否则无法使用orm 否则,编译错误 错误 5 "System.Data.Entity.DbSet`1<DbAccess.Entity.Dept>"不包含"Where"的定义,并且找不到可接受类型为"System.Data.Entity.DbSet`1<DbAccess.Entity.Dept>&qu

Highcharts使用时遇到的问题及解决方案

Highcharts使用时遇到的问题及解决方案 Highcharts图表控件功能强大,对细节处理得很细致,是目前使用最为广泛的图表控件.本文总结了作者在使用Highcharts时遇到的问题及解决方案. 1. 图表颜色设置 图表的边框色,背景色及点.线的颜色都是可以设置的,其中边框色(borderColor).背景色(backgroundColor)在chart中设置: chart: { backgroundColor: 'pink',// 背景色 borderColor: 'red',// 边框

bootstrap使用时 细节心得

最近国庆7天 还原某丽说 APP PC端网页(作业)时  全程使用bootstrap制作 也遇到了以前很少碰到过的问题 bootstrap 本身修改了某些默认样式  即使在 未给标签class命名某个bootstrap模板时  某些标签也被修改过  这样会容易使某些像我一样的新手误以为自己写的代码哪里出了问题  而浪费很多时间去找一个 没有错误的错误  所以在这里给各位同学做个温馨提示 例如 fieldset 中 lengd标签中的文字 应该是水平居中 位于两侧横线中间 并且垂直居中于横线 但在

c语言:宏里面参数不加括号容易出错,在使用时尽量加括号及举例

宏里面参数不加括号容易出错,在使用时尽量加括号 程序1: #include<stdio.h> #define SQARE(X) X*X int main() { int  n = 10; int m=SQARE(n); printf("m=%d\n",m); return 0; } 结果: m=100 请按任意键继续. . . 分析:貌似没有出问题,请看下面两个例子 程序2: #include<stdio.h> #define SQARE(X) X*X int 

RHEL6.5上Oracle ACFS与Linux samba一起使用时遇到的bug

RHEL上的Oracle ACFS与linux samba一起使用时遇到的bug 一.环境介绍: cat /etc/issue的结果为: Red Hat Enterprise Linux Server release 6.5 (Santiago) Kernel \r on an \m GI的详细patch信息:仅仅安装了GI的11.2.0.4版本,没有打任何的GI psu,没有打任何的GI patch 二.问题说明: 这是一套rhel6.5的rac,使用的是Oracle GI集群软件,使用了ac

解决导航、Tabbar、tableview配合使用时,tableview错位的问题

导航.Tabbar.tableview配合使用时,tableview会出现错位的情况,特别是除tabbar的第一个选项的tableview, 解决方法非常简单,如下: self.tabBarController = [[UITabBarController alloc] init]; self.tabBarController.edgesForExtendedLayout = UIRectEdgeNone;//防止tableview错位 _tabBarControllerNav = [[UINa

在使用时的区别是当我们想访问一个对象(object)的元素dollars 和yens

以上两种定义的唯一区别在于左边的定义中我们给了union一个名字price,而在右边的定义中我们没给.在使用时的区别是当我们想访问一个对象(object)的元素dollars 和yens 时,在前一种定义的情况下,需要使用: book.price.dollars book.price.yens 而在后面一种定义下,我们直接使用: book.dollars book.yens 再一次提醒,因为这是一个联合(union),域dollars 和yens 占据的是同一块内存空间,所以它们不能被用来存储两