文档章节

Java并发编程初级篇(八):ThreadLocal

阿拉德大陆的魔法师
 阿拉德大陆的魔法师
发布于 2016/11/23 16:30
字数 670
阅读 210
收藏 1

码上生花,ECharts 作品展示赛正式启动!>>>

 

在Java中,如果使用了Runnable接口的实现类。用这个实现类的一个实例对象来启动多个线程,那么这个类中的变量就会被多个线程共用,不管你住没注意,这在“Java并发编程(一):线程实现与运行的两种方式”中已经出现过了。

我们现在基于这个例子来改造一下,看如何用一个Runnable的实例对象创建多个线程类,并且让每一个线程都有自己的私有属性。

我们用Java API提供的ThreadLocal类来替换int变量,ThreadLocal类作为Java API提供的一个线程局部变量,它是和线程绑定的,每一个线程都会有一个独立的副本。

通过查看ThreadLocal类的原代码,我们可以发现每一个线程内部都会有一个ThreadLocalMap属性,这个类的内部实现是一个Entry[]数组,(key=ThreadLocal,value=ThreadLocal对象的绑定值)。当你调用ThreadLocal.get()方法的时候,它就会获取当前线程对象的ThreadLocalMap属性中以ThreadLocal对象为健对应的值。如果不存在就会调用setInitialValue()方法,然后将initialValue()方法返回的值设置到ThreadLocalMapEntry[]数组中,并返回这个值。

/**
     * Returns the value in the current thread's copy of this
     * thread-local variable.  If the variable has no value for the
     * current thread, it is first initialized to the value returned
     * by an invocation of the {@link #initialValue} method.
     *
     * @return the current thread's value of this thread-local
     */
    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null)
                return (T)e.value;
        }
        return setInitialValue();
    }

/**
     * Variant of set() to establish initialValue. Used instead
     * of set() in case user has overridden the set() method.
     *
     * @return the initial value
     */
    private T setInitialValue() {
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
        return value;
    }

下面看我们的实现代码,为线程定义一个ThreadLocal类型属性,具体实现ThreadLocal中的initialValue()方法来为这个ThreadLocal对象属性赋一个初始值。然后使用MyRunnable的一个实例启动三个线程。

public class MyRunnable implements Runnable {
    private ThreadLocal<Integer> num = new ThreadLocal<Integer>(){
        @Override
        protected Integer initialValue() {
            return 3;
        }
    };

    @Override
    public void run() {
        while (num.get() > 0) {
            System.out.println("Thread:" + Thread.currentThread().getName() + ", consume " + num.get());
            num.set(num.get() - 1);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        Runnable runnable = new MyRunnable();

        Thread thread1 = new Thread(runnable);
        Thread thread2 = new Thread(runnable);
        Thread thread3 = new Thread(runnable);

        thread1.start();
        thread2.start();
        thread3.start();
    }
}

查看控制台日志,你会发现每一个线程都使用了一个独立的num值。

Thread:Thread-0, consume 3
Thread:Thread-2, consume 3
Thread:Thread-1, consume 3
Thread:Thread-0, consume 2
Thread:Thread-1, consume 2
Thread:Thread-2, consume 2
Thread:Thread-2, consume 1
Thread:Thread-1, consume 1
Thread:Thread-0, consume 1

 

© 著作权归作者所有

阿拉德大陆的魔法师
粉丝 27
博文 91
码字总数 83019
作品 0
西城
程序员
私信 提问
加载中
请先登录后再评论。
送java学习资料,学会了这些你就是大神

本文已收录至公众号:灰太狼学爪哇。(一个java程序员都在关注的公众号) 前言 最近我发现,关注我领取学习资料的都是一些java初学者,有些还没走出校门,而我是一个已经工作有三年多的老油条...

osc_jegm3yg5
03/08
5
0
10 本 Java PDF 书籍免费分享

极力推荐文章:欢迎收藏Android 干货分享 本篇文章主要分享以下开发书籍 一、Java编程思想二、Effective Java三、Java核心技术卷四、Java并发编程实践五、深入理解Java虚拟机六、Java解惑七、...

osc_03aaqmm8
2019/08/09
6
0
JavaEE程序员必读图书大推荐

下面是我根据多年的阅读和实践经验,给您推荐的一些图书: 第一部分: Java语言篇 1 《Java编程规范》 星级: 适合对象:初级,中级 介绍:作者James Gosling(Java之父),所以这本书我觉得...

长平狐
2012/11/12
2K
0
Java初级进阶中高级工程师必备技能

很多人学了javase以为自己学的已经很OK了,但是其实javase里边有很多的知识点是你不知道的,不管你找的是哪里的javase的视频,大多数是不会讲这些东西,而这些东西你平时业务又不会主动去接触...

osc_7k19h8y1
2019/04/26
4
0
Java工程师学习指南 中级篇

Java工程师学习指南 中级篇 最近有很多小伙伴来问我,Java小白如何入门,如何安排学习路线,每一步应该怎么走比较好。原本我以为之前的几篇文章已经可以解决大家的问题了,其实不然,因为我写...

osc_ghkchgqq
2019/03/10
17
0

没有更多内容

加载失败,请刷新页面

加载更多

Java 项目工程搭建 --创建子模块(Spring Initializr)

一下篇,常用 Java 项目工程搭建 --创建子模块(依赖父工程) 也不算常用,常用的是 ctrl+c、ctrl+v ,哈哈 Package要手动改下,生成的很丑 选能支持 Alibaba Cloud 的版本 不然会跑到根目录...

osc_qheq8wav
27分钟前
13
0
C++指针相关问题

C++指针相关问题 一、总结 一句话总结: a、数组名是这个数组的首地址:a[3][4]:a int(*)[4]、&a int(*)[3][4]、a[0] int*、a[0][0] int b、int ** 表示指向指针的指针:int m = 1; int *p...

osc_35ne77sz
28分钟前
13
0
好兄弟仅用3年,就做到了架构师的位置,真心羡慕!经验分享给你

昨天跟好兄弟聊天,得知了他最近晋升了架构师的消息,是真的羡慕。要知道,我这个兄弟仅用了三年的时间,就做到了架构师的位置,真的优秀! 懂得多门主流编程语言如C++、Java、python等,可以...

osc_vnopwmym
29分钟前
13
0
C 实战练习题目40

题目:将一个数组逆序输出。 程序分析:用第一个与最后一个交换。 实例: 1 #include<stdio.h> 2 #define N 10 3 int main() 4 { 5 int a[N]={0,1,2,3,4,5,6,7,8,9}; 6 int i,...

osc_o1iwxx3z
31分钟前
33
0
C 实战练习题目36 – 求100之内的素数

题目:求100之内的素数。 程序分析:质数(prime number)又称素数,有无限个。一个大于1的自然数,除了1和它本身外,不能被其他自然数整除。 实例: 1 #include<stdio.h> 2 #include<mat...

osc_t4xzns0d
32分钟前
23
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部