一. Integer

1.引子

在开始之前,我还是需要吐槽下自己,我是真的很菜!

  • 他问:**两个Integer对象==比较是否相等?
  • 我答:对象==比较,是引用比较,不相等!
  • 他问:IntegerCache这个用来干什么?
  • 我答:......,我不是很清楚!!!

从这里可以看出,我是真的很水!!

基于这些原因还有其他的等等,我开始写博文,开始写踩过的坑!

2.IntegerCache

在介绍这个缓存之前,先来认知下Integer。java中,int是基本的数值类型,表示整型;Integer是其对象的表示,是int的包装类。包装类在Jdk1中就存在,但是为了更方便的使用Integer,在Java SE5中引入自动包装和自动拆箱的机制,这里不再赘述,可以移步至深入剖析Java中的装箱和拆箱

Java SE5可以说是java版本迭代过程中里程碑版本。为了减少大量创建Integer的开销、提高性能,采用享元模式,引入Integer实例缓存,将-128至127范围数值的Integer实例缓存在内存中,这里的缓存就是使用Integer中的辅助性的私有IntegerCache静态类实现。

先看下如何获取缓存的-128至127范围的Integer实例,这里的范围可以通过JVM启动参数修改,后面会讲述

  • 可以通过使用静态valueOf方法获取 // api调用
  • 可以使用自动包装机制获取,如:Integer a = 100; // autoboxing

这里基于Java SE8,再来看下IntegerCache的实现:

/**
* Cache to support the object identity semantics of autoboxing for values between
* -128 and 127 (inclusive) as required by JLS.
*
* The cache is initialized on first usage. The size of the cache
* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
* During VM initialization, java.lang.Integer.IntegerCache.high property
* may be set and saved in the private system properties in the
* sun.misc.VM class.
*/ private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[]; static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h; cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++); // range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
} private IntegerCache() {}
}

从java docs中可以看出,该类是为了支持对-128至127范围数值自动包装的实例进行缓存。

在第一次使用时缓存被初始化,缓存的大小可以通过JVM参数-XX:AutoBoxCacheMax=size控制,IntegerCache的high可以通过在JVM启动时设置系统属性变量java.lang.Integer.IntegerCache.high,以达到更强的灵活性。IntegerCache在执行类构造器初始化时,执行静态语句块,利用for循环从low开始不断自加加,然后放入cache数组中。

选择-128至127范围,是因为这个范围内的数值使用更普遍!

介绍到这里,相信已经不难看出我的回答是多么搞笑,我坐井观天的还以为自己是正确的!

说到这里,我又有些感慨了,昨晚看了集火影,刚好是自来也和佩恩的对话,佩恩对曾经的师傅自来也的一席话,虽然是偏执的,但是无可否认的确是对的。

佩恩把自己称为神,将自来也视作为凡人,说凡人的认知具有局限性,活在狭小的空间内自认为自己认识都是对的,殊不知从神的角度考虑,凡人的那些认知都是错误和愚蠢的。

这里旨在单纯思考佩恩这些话在我们现实生活中的含义:的确,在我们认知有限的时候,以为Integer两个对象==比较,应该是不等的,殊不知因为技术掌握有限。

跑题了,引入一段故事,主要是想铭刻下,吸取教训:不要把事物看做是理所当然,要多多思考其本质和原理;不要妄下结论,小心求证!

不仅是Integer,Short、Byte、Long、Char都具有相应的Cache。但是Byte、Short、Long的Cache有固定范围:-128至127;Char的Cache:0至127。

引用

理解Java Integer的缓存策略

二. ThreadLocal

我这里不再赘述ThreadLocal是什么、解决什么问题、实现原理、应用场景等,网上博文非常丰富,可移步至深入剖析ThreadLocal

这里主要是分析下ThreadLocal在父子线程中共享的问题。

ThreadLocal不提供对子线程共享父线程的ThreadLocal中存储的value的支持,ThreadLocal的get方法返回与当前线程有关的ThreadLocalMap中的key/value,如下图:

/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;

每个线程在创建的时候,都会初始化ThreadLocalMap的空引用。 子线程在创建时ThreadLocaMap是null,所以不共享父线程的ThreadLocalMap中key/value。

但是有很多时候,实际需求需要共享父线程的一些状态值。 这种情况,java也对此提供了支持,只能说设计者们的脑洞大开。

java中引入另一个InheritableThreadLocal类对此提供支持,类名给出了用途的最好表示:可继承的ThreadLocal

/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;

同理,每个线程在创建的时候都会初始化InheritableThreadLocal

的引用,然后在线程执行初始化的生命周期阶段时,对该变量进行初始化操作,如下图:

    if (parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);

线程的初始化周期中,首先判断父线程的ThreadLocal是否为空,如果不为空则根据父线程的inheritableThreadLocals创建子线程的inheritableThreadLocals。

InheritableThreadLocal的实现也非常简单:

  • childValue: 计算子线程的初始化值,从这个方法中可以知道,子线程使用的是父线程中的value,并不是拷贝,如果需要使用副本拷贝,可以继承重写
  • getMap: 返回当前线程持有的inheritableThreadLocals
  • createMap: 如果当前线程的inheritableThreadLocals是空,则创建一个

以上三个api都是重写ThreadLocal的。

Java中Integer和ThreadLocal的更多相关文章

  1. java中Integer比较需要注意的问题

    java中Integer比较需要注意的问题 package com.srie.test; import java.util.HashMap; import java.util.Map; public ...

  2. java中Integer 和String 之间的转换

    java中Integer 和String 之间的转换 将数组转换成字符串:char[] array = {'a','b','c','d','e'};String str = new String(ar ...

  3. Java中Integer的最大值和最小值

    从JDK1.0开始,Integer中就定义了MIN_VALUE和MAX-VALUE两个常量: /** * A constant holding the minimum value an {@code ...

  4. 从源码看java中Integer的缓存问题

    在开始详细的说明问题之前,我们先看一段代码 public static void compare1(){ Integer i1 = 127, i2 = 127, i3 = 128, i4 = 128; ...

  5. Java中Integer的源码学习

      一.开始 public final class Integer extends Number implements Comparable<Integer> 1).由于类修饰符中有关键字 ...

  6. Java中Integer类的方法

    java.lang 类 Integer java.lang.Object java.lang.Number java.lang.Integer 全部已实现的接口: Serializable, Comp ...

  7. Java中Integer和String浅谈

    Java中的基本数据类型有八种:int.char.boolean.byte.long.double.float.short.Java作为一种面向对象的编程语言,数据在Java中也是一种对象.我们用基本 ...

  8. JAVA中Integer的==和equals注意

    “equals”比较:equals(Object obj)方法,在equals(Object obj)方法中,会先判断参数中的对象obj是否是Integer类型的对象,如果是则判断值是否相同,值相同则 ...

  9. JAVA中Integer类型变量比较问题

    今天在做实验的时候,发现了一个比较奇怪的问题:两个Integer型变量用==进行比较时,有时候能成功有时候不能成功.举个例子: 代码1: Integer l1 = 122; Integer l2 = ...

随机推荐

  1. Spring面试专题之aop

    1.背景 aop是编程中非常非常重要的一种思想,在spring项目中用的场景也非常广 2.面试问题 2.1.简单的面试问题 1.什么是aop,aop的作用是什么? 面向切面编程(AOP)提供另外一种角 ...

  2. php-fpm编译安装脚本

      PHP是开源.轻量级.高效的开发语言,特别适合web项目开发,在中小型互联网公司中常用于开发web后端.PHP常与Nginx及MySQL数据库结合,搭建LNMP环境.以下为centos7系统下ph ...

  3. Rikka with Travels(2019年杭电多校第九场07题+HDU6686+树形dp)

    目录 题目链接 题意 思路 代码 题目链接 传送门 题意 定义\(L(a,b)\)为结点\(a\)到结点\(b\)的路径上的结点数,问有种\(pair(L(a,b),L(c,d))\)取值,其中结点\ ...

  4. LOJ 3120: 洛谷 P5401: 「CTS2019 | CTSC2019」珍珠

    题目传送门:LOJ #3120. 题意简述: 称一个长度为 \(n\),元素取值为 \([1,D]\) 的整数序列是合法的,当且仅当其中能够选出至少 \(m\) 对相同元素(不能重复选出元素). 问合 ...

  5. 第07节-开源蓝牙协议BTStack框架代码阅读(上)

    首先来看一下,对于硬件操作,它是如何来进行处理的.在上篇文章中曾说过,在main函数里面它会调用硬件相关的代码,调用操作系统相关的代码.在BTStack中,可以搜索一下main.c,将会发现有很多ma ...

  6. 接口测试:postman

    测试接口,postman和jmeter是用得最频繁的工具. 下面主要介绍postman测试http协议接口的用法,包含get,post(form-data,json,上传文件,cookie). pos ...

  7. MongoDB在windows及linux环境下安装

    linux下安装配置 整理中... windows下安装配置 1.下载: https://www.mongodb.com/download-center?jmp=nav 2.解压到D盘 3.D:\下创 ...

  8. 16-cmake语法-OpeCV3.3.1_CMakeLists.txt的部分注释

    OpeCV3.3.1 的 CMakeLists.txt 的部分注释. # Disable in-source builds to prevent source tree corruption. # @ ...

  9. DB2数据库

    必需步骤: 您已经启用了 DB2 扩展 Windows 安全性.您必须将运行 DB2 本地应用程序或工具的 DB2 用户添加至 DB2ADMNS 或DB2USER 组 可以使用端口号 "50 ...

  10. csv与openpyxl函数

    csv 与openpyxl函数 csv函数 常用的存储数据的方式有两种--存储成csv格式文件.存储成Excel文件(不是复制黏贴的那种) 前面,我有讲到json是特殊的字符串.其实,csv也是一种字 ...