博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
线程局部变量的使用
阅读量:7156 次
发布时间:2019-06-29

本文共 2861 字,大约阅读时间需要 9 分钟。

hot3.png

共享数据是并发程序最核心的问题之一,对于继承了Thread类或者实现了Runnable接口的对象来说尤其重要。如果创建的对象是实现了Runnable接口的类的实例,用它作为传入参数创建多个线程对象并启动这些线程,那么所有的线程将共享相同的属性。也就是说,如果你在一个线程中改变了一个属性,所有线程都会被这个改变影响。

在某种情况下,这个对象的属性不需要被所有线程共享。Java并发API提供了一个干净的机制,即线程局部变量(Thread-Local Variable),其具有很好的性能。

这里我们将创建两个程序:第一个具有刚才提到的问题。另一个使用线程局部变量机制解决了这个问题。

第一个示例,显示共享才生的问题:

package concurrency;import java.util.Date;import java.util.concurrent.TimeUnit;public class Main3 {    public static void main(String[] args) {        UnsafeTask task = new UnsafeTask();        for(int i=0; i<10;i++){            Thread thread = new Thread(task);            thread.start();            try {                TimeUnit.SECONDS.sleep(2);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}class UnsafeTask implements Runnable{    private Date startDate;    @Override    public void run() {        startDate = new Date();        System.out.printf("Starting Thread:  %s  :  %s\n", Thread.currentThread().getId(),startDate);        try {            TimeUnit.SECONDS.sleep((int)Math.rint(Math.random()*10));        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.printf("Thread Finished:  %s  :  %s\n", Thread.currentThread().getId(),startDate);    }}

第二个示例,例用线程局部变量解决第一个示例中的问题:

package concurrency;import java.util.Date;import java.util.concurrent.TimeUnit;public class Main4 {    public static void main(String[] args) {        SafeTask task = new SafeTask();        for(int i=0; i<10;i++){            Thread thread = new Thread(task);            thread.start();            try {                TimeUnit.SECONDS.sleep(2);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}class  SafeTask implements Runnable{    private static ThreadLocal
 startDate = new ThreadLocal
(){        protected Date initialValue(){            return new Date();        }    };    @Override    public void run() {        System.out.printf("Starting Thread:  %s  :  %s\n", Thread.currentThread().getId(),startDate.get());        try {            TimeUnit.SECONDS.sleep((int)Math.rint(Math.random()*10));        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.printf("Thread Finished:  %s  :  %s\n", Thread.currentThread().getId(),startDate.get());    }}

声明一个ThreadLocal<Date>对象。Date的对象是在initialValue()方法中隐式实现的,这个方法将返回当前日期。线程局部变量分别为每个线程存储了各自的属性值,并提供给每个线程使用。你可以使用get()方法读取这个值,并用set()方法设置这个值。如果线程是第一次访问线程局部变量,线程局部变量可能还没有为它存储值,这个时候initialValue()方法就会被调用,并且返回当前的时间值。

线程局部变量也提供了remove()方法,用来为访问这个变量的线程删除已经存储的值。Java并发API包含了InheritableThreadLocal类,如果一个线程是从其他某个线程中创建的,这个类将提供继承的值。如果一个线程A在线程局部变量已有值,当它创建其他某个线程B时,线程B的线程局部变量将跟线程A是一样的。你可以覆盖childValue()方法,这个方法用来初始化子线程在线程局部变量中的值,它使用父线程在线程局部变量中的值作为传入参数。

转载于:https://my.oschina.net/fhd/blog/406457

你可能感兴趣的文章
JS: addEventListener 和 attachEvent 绑定的函数中this的区别
查看>>
java中的抽象类和抽象方法
查看>>
vue中使用animate.css
查看>>
mongodb的使用方法
查看>>
2820: YY的GCD
查看>>
hdu1811 并查集+拓扑序
查看>>
discuz论坛几种安全策略(二)
查看>>
类中const, static, reference成员的初始化
查看>>
nginx.conf的events,http段一般固定配置
查看>>
Lambda表达式常用代码示例
查看>>
夏季训练DAY2(二分&三分)
查看>>
find the mincost route HDU - 1599 (最小环)
查看>>
UML用例图
查看>>
python 一致性哈希 分布式
查看>>
ANUSPLINE气象插值入门教程
查看>>
Js:消息弹出框、获取时间区间、时间格式、easyui datebox 自定义校验、表单数据转化json、控制两个日期不能只填一个...
查看>>
通过IP地址屏蔽各种“推广”
查看>>
virtualenv下配置nginx uwsgi Django
查看>>
vscode左侧文件不同颜色标识含义
查看>>
CF 1182F Maximum Sine——根号算法
查看>>