`
QING____
  • 浏览: 2234195 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java.lang-API整理(3)

    博客分类:
  • JAVA
 
阅读更多

十.InheritableThreadLocal类(继承性ThreadLocal)

InheritableThreadLocal类继承自ThreadLocal,它具有ThreadLocal的所有特征,同时它还具有能够访问其父线程绑定的数据.但是其父线程不能访问其绑定的数据.

感觉就像父线程set的值被"继承下来"一样,但是子线程只能get父线程绑定的值,不能通过set去重置父线程的值,因为子线程set,将会导致将新值与子线程绑定,而非修改父线程的value.

ThreadLocal实例可以与一个"value"绑定,并在当前线程的任何进度中,获取此value.ThreadLocal内部的数据通过一个ThreadLocalMap数据结构来维护,每个ThreadLocal实例均会维护2个ThreadLocalMap属性:

1) threadLocals:维护当前线程中所有的ThreadLocal实例

2) inheritableThreadLocals:维护从父线程"继承"下来的所有ThreadLocal.

对于ThreadLocal类,从ThreadLocal中获取值的过程为:使用当前ThreadLocal实例作为key,从当前线程的threadLocals中获取value.

 

///////
Thread t = Thread.currentThread();
return t.threadLocals.get(this);
//////
 

 

但是对于InheritableThreadLocal类,有个问题需要明确,否则会在编程中带来陷阱:

1) 如果没有子线程使用InheritableThreadLocal,那么它和ThreadLocal具有一样的特性.

2) 如果有子线程,那么子线程Thread实例在初始化时(new Thread())时,将会把做如下操作:

subThread.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);

此操作的底层实现把parent.inheritableThreadLocals内容浅copy一份交给subThread.

再次需要清楚,Thread维护2个ThreadLocal属性应用,同时自定义的ThreadLocal实例的绑定值与Thread具有对应关系.

3) 根据2)可知,在subThread中,使用InheritableThreadLocal实例去get,仍然会得到在父线程中set的值.(因为我们底层对map做了一次浅copy,所以根据InheritableThreadLocal实例引用作为key,完全是可以得到在父线程set的值)

4) 此后,如果子线程中,对InheritableThreadLocal实例操作了set,那么将会更改subThread.inheritableThreadLocals中所维护的值.

即在子线程中任何时候再次调用get,将会得到新值.(只是改变了subThread所维护的信息)

5) 即使在subThread中修改了InheritableThreadLocal实例绑定的值,那么在父线程中去get,仍然只能得到null或者父线程先前自己set的值,仍然不能得到子线程set的新值.

因为父线程Thread实例和subThread是2个完全不同的对象,所以它们的inheritableThreadLocals属性并不是共享的(各自维护),只不过subThread在创建时copy了一份而已.

6) 子线程创建之后,父线程中对InheritableThreadLocal实例操作了set,那么子线程将不会得到新值(因为copy已经发生过了)

 

十一.Runtime类

每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime 方法获取当前运行时。Runtime实例不能被直接创建,是有VM自行创建.但是可以通过getRuntime()获取系统的运行时实例.

  • public static Runtime getRuntime();返回系统的runtime实例,Runtime类没有扩展seriazable接口,不能被序列化.Runtime实例更像是单利模式:私有构造器,内部持有static Runtime instance.
  • public void exit(int status):通过启动虚拟机的关闭序列,终止当前正在运行的java虚拟机.此方法无返回值.status为状态码,非零的状态码表示非正常终止.

虚拟机的关闭序列包括2个阶段:

1) 第一阶段,会以某种未指定的顺序启动所有的已注册的"关闭钩子(hood)",并且允许它们同时运行直至结束.

2) 第二阶段,如果已启动"退出终结(Finalizor)",则运行所有未调用的终结方法(finalize())

一旦完成这个阶段,虚拟机就会暂停.如果在虚拟机已开始其关闭序列后才调用此方法,那么若正在运行关闭钩子,则将无限期地阻断此方法。如果已经运行完关闭钩子,并且已启用退出终结 (on-exit finalization),那么此方法将利用给定的状态码(如果状态码是非零值)暂停虚拟机;否则将无限期地阻断虚拟机。

 

System.exit(1)是我们常用的,非正常退出系统的方式,其内部是使用runtime.exit(status).

对于status的值,只有0和非零两中状态,0表示正常退出即运行结果符合预期时退出,非零(>0或者<0)均表示异常退出,异常退出的代码我们会经常放在catch块中.

无论status值是多少,最终都会导致JVM退出,status值只是一个"information",可以被其他监控工具或者日志系统中获得status.大部分时候,我们可以通过定义不同的status,来观察系统异常退出的时机.

  • public void addShutdownHook(Thread thread):注册新的虚拟机关闭hook.底层使用IdentityHashMap保存hooks信息,key和value都是Thread实例.

JVM会响应如下两类事件而关闭:

1) 程序正常退出,这发生在最后的非守护线程退出时,或者调用exit方法时.(基于程序内部退出)

2) 为响应用户中断而终止 虚拟机,如键入 ^C;或发生系统事件,比如用户注销或系统关闭。 (基于OS系统或者外部因素关闭)

 

hook是一个已经初始化但尚未执行的thread.注册的所有hooks将会以未知的顺序同时被执行.所有hooks执行完成之后,如果已经启动"退出终结",那么VM将运行所有未调用的终结方法.最后VM会暂停.在VM关闭期间,daemon线程继续运行,直到VM暂停.

如果已经开始了"关闭序列",则只能通过halt(status)方法来停止,此方法是忽略任何关闭序列强制终止VM.

如果已经开始了"关闭序列",则不能再次注册新的hook,此时将会抛出IllegalStateException.

hook是需要在VM生命周期中特定时期执行,所以需要对hook的编码特别注意:

1) 需要注意同步,因为hooks可以被并行执行.且hooks对资源引用不能出现死锁

2) hook中执行的业务需要非常简洁,避免耗时的任务.因为OS只允许VM在固定时间内退出

如果虚拟机被外部操作干扰,如killall等,有可能会导致VM不能执行完所有的hooks即被终止.

  • public boolean removeShutdownHook(Thread thread):移除先前注册的且尚未被执行的hooks.
  • public void halt(int status):强制终止正在运行的VM.此方法和exit不同,此方法将不会启动hooks,并且如果已经启动"退出终结",那么次方法也不会运行未被执行的finalize方法.[更加强制性的中断操作],在任何关闭序列,此方法不会等待"关闭序列"执行完成,而是直接强制终止.status的意义和exit方法中status一样.0表示正常,非零表示非正常.
  • public static void runFinalizersOnExit(boolean):此方法已过期,用来控制在退出时是否执行finalize方法,是一个开关操作.因为其不安全性,导致死锁或者资源问题,deprecated.
  • public Process exec(String command):运行一个command,并且返回此command的监视进程.command为一个系统指令.process是一个独立的进程,可以用来监视command进程的执行情况,甚至可以关闭进程等.
    /////////////////Process
    Process p = Runtime.getRuntime().exec("notepad");//获取notepad进程
    p.waitFor();//阻塞直到进程关闭
    //p.destroy();//关闭进程
  • public int availableProcessors():获取VM可用处理器的数量
  • public long freeMemory():获取VM中空闲内存量,此值为近似值,以字节为单位.totalMemory()获取VM已使用内存量.maxMemory()获取VM可以使用的最大内存量.
  • public void gc():等效于System.gc.
  • public void runFinalization():运行挂起的所有对象的finalize方法.JVM只是尽力去执行,但并不意味着VM一定会全部执行..此方法返回时,标明VM已经尽力完成了可以执行的终结方法.等效System.runFinalization()
  • public void traceInstrucations(boolean):启动/禁用指令跟踪.如果为true,VM会发送每条指令执行的调试信息.traceMethodCalls(boolean)是否开启方法调用的信息.

十二.String

String扩展自CharSequece接口,String采用Unicode字符集,UTF-16编码,即16位标识一个字符.

构造方法:

  • String(byte[] bytes,Charset set):根据指定的字符集,将byte[]构建成String
  • String(char[] sequeuce):将char数组转化成String
  • String(String original):复制一个String.
  • String(StringBuffer/StringBuilder):toString.

每个String对象内部维护着字符串的length和char[]数组,即底层使用char[]保存String内容.

方法列表:

  • public boolean contains(CharSequece cs):逐个依次检测字符在原始char数组中是否出现.
  • public boolean contentEquals(CharSequece cs):比较内容是否一致.
  • public int codePointAt(int index):获取指定索引出的字符Unicode代码点.
  • public byte[] getBytes(String charsetName):使用指定的字符集将String编码为byte序列.
  • public native String intern():对当前字符串进行常量池检测,如果它已经在常量池中,则直接返回常量池中此串的引用,否则将此字符串添加到常量池中并返回.

十三.StringBuffer类

StringBuffer类和String一样扩展自CharSequece,它维护一个长度可变的字符串集合,底层为一个char数组.当字符串的长度超过容量时将重新分配空间..这也是apend操作的实现手段,在插入前,检查容量是否达到阀值,如果是,则重新分配容量并数据copy(扩大2倍).

StringBuffer是线程安全的.所有的append/insert/delete方法都是synchronized.

StringBuilder和StringBuffer相比,无法保证线程安全性.

 

十四.System类

提供了一些辅助方法,也提供了一些标准输入/输出/错误流,可以访问系统属性,加载类库等..和Runtime类有些共通点.

/////常量属性

  • static final PrintStream out//err;//标准输出流,此流对应于显示器输出或者外部环境输出.
  • static final InputStream in;//标准输入流,表示键盘输入或者外部环境输入.
  • staitc Console console():返回与当前java虚拟机关联的唯一的Console对象(如果有)
  • public static void setSecurityManager(SecurityManager s):设置系统安全性.如果系统已经安装了SecurityManager,此方法首先通过 RuntimePermission("setSecurityManager") 权限调用安全管理器的 checkPermission 方法,以确保可以替换现有的安全管理器。这可能导致抛出一个 SecurityException 异常。
  • public static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length):数组copy,常用的Arrays.copy其实就是基于此方法操作.从指定src的srcPos开始复制,到目标数组的指定位置.此方法为native方法.
  • public static int identityHashCode(Object o):返回给定对象的hashCode,等效于默认的hashCode(),即使重写hashCode方法,任然不会干扰此方法获取一致性hash值.
  • public static Properties getProperties():获取java的系统属性,参见java系统属性列表.
  • public staitc Property getProperty(String key):获取指定的系统属性.
  • public static getenv(String name):获取操作系统中的环境变量值.例如:System.getenv("path").

 

备注:

IdentityHashMap,一种特殊的hashmap存储结构,底层仍基于数组保存,不过数组中并没有hash冲突的结局,因为它使用的hashcode是根据System.identityHashCode(key),因此key的hashcode值是系统的,不受到hashcode方法的重写而影响;判断key是否一样,使用“==”而不是使用equals方法,这一点与HashMap有根本区别。IdentityHashMap底层使用数组存储,但是并没有使用链表解决hash冲突,因为identityHashCode值可以预见性的、冲突的机会较少,而且使用“==”判定可以准确的确定key-value;数组中,key、value相继存储,即“[K][ ][K][V]”,使用hashcode计算此key所在数组的起始位置:

    private static int hash(Object x, int length) {
        int h = System.identityHashCode(x);
        // Multiply by -127, and left-shift to use least bit as part of hash
        return ((h << 1) - (h << 8)) & (length - 1);
    }

    将hash冲突的key-value连续相邻的方式保存在数组中。在get操作时,使用遍历 + “==”判断:

    public V get(Object key) {
        Object k = maskNull(key);
        Object[] tab = table;
        int len = tab.length;
        int i = hash(k, len);
        while (true) {
            Object item = tab[i];
            if (item == k)
                return (V) tab[i + 1];
            if (item == null)
                return null;
            i = nextKeyIndex(i, len);//依次 + 2,直到数组尾部
        }
    }

 

分享到:
评论

相关推荐

    jakarta.activation-1.2.2-API文档-中英对照版.zip

    标签:activation、sun、jakarta、jar包、java、中英对照文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译...

    javax.el-api-3.0.0.jar

    springboot 打war部署到apache-tomcat-7.0.69中启动报错:java.lang.NoClassDefFoundError: javax/el/ELManager 下载javax.el-api-3.0.0.jar,放到 tomcat/lib包下可以解决,原来的el-api.jar版本较低

    javax.mail-api-1.6.2.jar

    通过错误描述我们发现java.lang.NoClassDefFoundError: javax/mail/MessagingException,主要说找不到这个类。通过查询发现是缺少javax.mail-api-1.6.2.jar和activation-1.1.1.jar包。在maven上下载即可

    com.springsource.tcl.lang.jacl-1.4.1生成报错替换包.zip

    com.springsource.tcl.lang.jacl-1.4.1生成报错替换包.zip

    jdk10+ java.lang.NoClassDefFoundError: javax/xml/ws/Service 错误

    jdk升级之后出现异常:java.lang.NoClassDefFoundError: javax/xml/ws/Service 1、解决方案jdk降级至1.8之前 2、由于JDK9以后,去除了javax.xml包需要引入对应的jar包 &lt;groupId&gt;javax.activation &lt;artifactId&gt;...

    commons-lang3-3.9-API文档-中文版.zip

    标签:apache、commons、lang3、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请...

    xulrunner-1.9.2.28pre.en-US.linux-x86_64.tar.rar

    org.eclipse.swt.SWTError: No more handles [MOZILLA_FIVE_HOME=''] (java.lang.UnsatisfiedLinkError: Could not load SWT library. Reasons: no swt-mozilla-gtk-4335 in java.library.path no swt-mozilla-gtk ...

    ews-java-api-2.0

    EWS java API 里面包含 Java调用EWS 接口所需要的所有jar包如: commons-logging-1.2.jar joda-time-2.8.jar commons-lang3-3.4.jar httpclient-4.4.1.jar httpcore-4.4.1.jar

    org.apache.commons.lang jar包下载(commons-lang3-3.1.jar)

    commons-lang3.3.1.jar、Apache Commons包中的一个,包含了一些数据类型工具类,是java.lang.*的扩展。必须使用的jar包。为JRE5.0+的更好的版本所提供 Jar文件包含的类: META-INF/MANIFEST.MFMETA-INF/LICENSE....

    javax.servlet-api-3.1.0

    java.lang.IllegalStateException: Failed to read Class-Path attribute from manifest of jar file:/XXX 出现这个问题的解决方案就是将原有的jar删除 然后重新下载过一遍就可以使用

    idea启动项目报错 java.lang.NegativeArraySizeException解决方法

    idea启动项目报错 java.lang.NegativeArraySizeException解决方法

    scala-java8-compat_2.11-0.7.0-API文档-中文版.zip

    标签:scala、lang、modules、java8、compat、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明...

    standard-1.1.2.jar,jstl-api-1.2.jar,jstl-impl-1.2.jar,jstl-1.2.jar

    Tomcat启动报错 java.lang.ClassNotFoundException: org.apache.jsp.index_jsp,检查你的项目中是否存在jsp-api.jar,jstl-api.jar,servlet-api.jar。

    commons-lang3-3.12.0-API文档-中文版.zip

    标签:apache、lang3、commons、jar包、java、中文文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请...

    com.springsource.org.apache.commons.lang-2.6.0.jar

    jar包,官方版本,自测可用

    java.lang.NoSuchFieldError Companion

    java.lang.NoSuchFieldError: Companion 问题的解决方案

    vscode插件合集(20190814)part1

    ms-ceintl.vscode-language-pack-zh-hans-1.37.3 ms-ceintl.vscode-language-pack-zh-hans-1.37.5 mtxr.sqltools-0.20.1 ms-vscode-remote.remote-wsl-0.39.2 alefragnani.bookmarks-10.5.0 ms-vsliveshare....

    commons-lang3-3.10-API文档-中文版.zip

    标签:apache、commons、lang3、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请...

    java.lang.OutOfMemoryError解决办法

    报错 java.lang.OutOfMemoryError: PermGen space 报错 java.lang.OutOfMemoryError: Java heap 启动报错java.lang.ClassNotFoundException: 1catalina.org.apache.juli.FileHandler JAVA_OPTS="-server -Xms800m ...

    scala-reflect-2.12.14-API文档-中文版.zip

    标签:scala、lang、reflect、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请放心...

Global site tag (gtag.js) - Google Analytics