十.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,直到数组尾部 } }
相关推荐
这份"JAVA全套API手册整理.zip"包含的应该是一份详尽的Java API文档,帮助开发者理解和使用Java平台的各种功能。 Java API涵盖了许多关键领域,包括: 1. **基础类库**:如Object、String、ArrayList、HashMap等,...
根据提供的文件信息,我们可以整理出以下关于Java考试的要点及相关知识点: ### Java考试要点概览 #### 一、Java的历史与发展 - **起源**: Java语言最初由Sun Microsystems公司于1991年开始开发,最初命名为“Oak...
### Robotium 2.5 API 整理及详解 #### 一、概述 Robotium是一款用于Android自动化测试的开源框架,它可以模拟用户操作来进行UI测试。Robotium支持各种类型的测试,包括功能测试、系统测试以及接受性测试等。在...
这份“Java基础知识学习--自己整理.zip”压缩包显然是一个精心整理的Java初学者教程,包含了作者的学习笔记和心得,旨在帮助新手快速入门。下面将详细阐述Java的基础知识。 **一、Java简介** Java是由Sun ...
### Java 常用API的运用、效率及技巧 #### 1. Java 面向对象基本概念 Java 是一种完全面向对象的语言,除了几种基本数据类型(如 int、double 等)之外,所有事物都被视为对象。面向对象编程(OOP)的基本原则包括...
3. 动态代理:使用java.lang.reflect.Proxy实现动态代理。 八、JVM内存管理 1. 内存区域:了解堆、栈、方法区、程序计数器、本地方法栈等区域。 2. 垃圾回收:理解垃圾收集机制,探讨不同的垃圾收集器。 3. 内存...
本资料包"Java常用的插件API整理以及基于JDK的一些方法封装库.zip"主要包含了对Java插件API的详细整理和基于JDK的方法封装库,让我们一起来深入探讨。 首先,插件API(Plugin API)是软件系统中一种允许第三方...
3. **字符串操作**:`java.lang.String`类提供了大量的字符串处理方法,如concat()、substring()、trim()、indexOf()等,用于字符串连接、截取、去除空格、查找子串等操作。另外,`java.util.regex`包中的Pattern和...
【Java复习题与答案】 1. Java语言的注释: - 单行注释以`//`开始,用于简短的注释。...以上是根据提供的内容整理的Java相关知识点,涵盖了注释、类与继承、JVM特性、访问控制、程序结构、面向对象编程等多个方面。
3. **内部实现细节**:例如,`java.lang.Object`的`clone()`方法是如何工作的,`java.util.ArrayList`和`java.util.LinkedList`的性能差异,`java.io.InputStream`和`java.io.OutputStream`的抽象设计等。...
System 类位于 java.lang 包中,是 Java 中最重要的类之一。 3. String, StringBuffer String 和 StringBuffer 是 Java 中两个重要的类,String 用于表示字符串,StringBuffer 用于表示可变字符串。StringBuffer ...
- **分类**:标准库(如 `java.lang`、`java.util` 等)、第三方库等。 - **用途**:提供丰富的功能,简化开发工作。 ### 五、输入输出 (IO) - **定义**:用于处理文件读写等操作。 - **分类**:字节流(如 `...
### Java的考试复习资料整理 #### 一、Java的基本概念及语法 - **Java平台的三个版本**: - **Java ME** (Micro Edition):主要用于嵌入式系统和移动设备。 - **Java SE** (Standard Edition):标准版,适用于...
这份"Java程序员常用英语单词800+"的资料,是根据Java API中五个核心包(lang, util, io, net, sql)的高频词汇整理得出的,涉及文档超过1700个。这些单词在计算机软件开发环境中具有特定含义,不仅包含通用词汇,还...
- **JTA (Java Transaction API)**: 用于管理事务处理,提供了与平台无关的事务处理机制。 #### 7. forward 与 redirect 的区别 - **forward**: - 在服务器端进行的页面重定向,不改变浏览器地址栏中的 URL。 - ...
根据提供的文件信息,我们可以整理出以下关键的Java知识点: ### 1. Java 类与接口的实现 - **`java.lang.Thread`**: 在Java中,如果一个类想要创建线程,可以通过继承`java.lang.Thread`类或者实现`Runnable`接口...
* compact2:包含java.io、java.lang、java.util、java.text等API。 * compact3:包含所有的API。 使用javac命令可以根据profile编译应用程序,例如: $ javac -profile compact2 Test.java 如果不符合compact的...
这份"Java十大基础笔记整理(PDF)"提供了全面的Java基础知识概览,适合初学者进行学习和复习。下面,我们将深入探讨Java的基础知识,涵盖核心概念、语法和编程实践。 1. **Java简介**:Java是由Sun Microsystems...
以上只是Java核心知识的冰山一角,实际的"JAVA核心知识点整理.pdf"可能会包含更多细节,如枚举、并发工具类、Lambda表达式、Stream API、模块系统(Jigsaw)、NIO.2、JPA、Spring框架等内容。深入学习并掌握这些知识...
在个人整理的Java学习资料中,我们可以看到以下几个关键知识点: 1. **JavaDoc注解**:JavaDoc是一种生成API文档的工具,常用的标记如`@author`用于指定程序作者,`@version`表示源文件的版本,`@deprecated`标记...