分类 Java 相关 下的文章

Java String.intern() 方法

是什么? 为什么?

看到有个统计说, 在 JVM 的内存中, String 大概占到20% ~ 50% 的内存区, 那么这么多的 String 必定有很多重复的, 既然是重复的, 那就可以只在内存放一份, 所有使用这个 String 的 reference 都指向同一块内存. 那么 JVM 就在 permanet generation 放置了一个 StringSet(也有称 StringTable, StringCache), 当一个 String instance 调用 intern 方法的时候, 它先检查这个 String 在 StringSet 中是否存在, 如存在, 就返回这个存在的 String, 否则, 在 StringSet 中添加这个 String, 并且返回新加的这个 String.
这前提是基于: Java 的 String 是 immutable 的: 如果你改变了 String 的一部分, 原来的 reference 就指向了一个新的String. 如果都在原来的 String 的内存区修改, 那么就不能放到 StringSet 了.
另外, 编译器自动把你程序中的类名, 方法名, String 常量值, 字面值 等都事先放入了 StringSet. 这个 StringSet 是有 String 这个 class 所管理的.
类似的机制, 在整数类型 (Byte, Short, Integer, Long) 的 valueOf 方法中都有体现, 默认 -128 ~ 127 都放入了 cache.

优缺点?

如果你有大量的重复的 String 值要在程序中使用, 并且是运行时生成的 String, 通过 intern 方法, 会大大节省内存, 并且减少 GC 的量. 但是, 带来是效果是需要能多的时间. 时间 VS 内存. 关于时间和内存的比较, 详细可以看 refer 2.

如果是仅仅使用 intern 的值来用 == 对比, 完全没有必要, 时间上算起来, 差不多.


摘抄:
String interning takes a String instance (so it already exists in the Heap) and checks if an identical copy exists already in a StringTable.
That StringTable is basically a HashSet that stores the String in the Permanent Generation. The only purpose of that Table is to keep a single instance of the String alive. If it is in there, the instance is returned. If its not, its added to the String Table
Note that ALL Strings which are hardcoded (as constant or anywhere in code) are automatically interned by the compiler.

参考:

  1. Save Memory by Using String Intern in Java
  2. String spec

单例模式 -> ThreadLocal -> new

Java 是多线程, 面向对象的编程语言. 多线程有时候也需要 share 一个实例对象. 一个 JVM 中的多线程可能会产生如下的 share 模式:

  1. 所有线程使用同一个实例对象: 单例模式;
  2. 每个线程使用一个实例对象: ThreadLocal;
  3. 最普遍的, 一个实例对象就是内存堆中的一个实例对象: new

如何做到一个 JVM 中的 单例模式:

  1. 构造函数全都是 private
  2. 因为构造函数是 private, 所以只能该 class 提供一个唯一内部的 static instance. 该 static instance 可以通过 public 暴露, 或者通过一个 public static 方法暴露. 通过方法暴露, 可以 lazy init;

其实, 如上并不能保证一个 JVM 中只有一个 instance, 比如2个 ClassLoader 在同一级, 分别 load 该 class, 或者反序列化该类;

ThreadLocal

前面要加 static final 修饰符. 不加 static, 不能确保一个线程只有一个实例. 不加 final, 可能会被改变的

How to create a java object?

  1.    new Object();
    
  2.    Class.forName(“com.txhcqy.A”).newInstance();
    
  3.    反序列化
    
  4.    反射机制中的Constructor
    

java monitor lock

每个 Java 对象都关联一个 monitor, 运行的线程可以对 monitor 进行 lock 或者 unlock. 同一时刻, 只能有一个线程获得一个对象的锁, 其它尝试获得此锁的线程都被 block 住, 直到当前线程释放此锁.

要使用 java.lang.Object 的 wait, notify 方法, 必须获得此对象的 monitor 的 lock, 所以 wait, notify, notifyAll 必须在获得此锁的 synchronized 的代码块中.

最基本的线程等待, 是使用 while(true) { //break 条件 或启动新线程/进程去做事;}, 但是这种是一直占用 CPU, 称之为 busy waiting. 如果想暂时不占 CPU 可以让线程 inactive, 等到一定条件唤醒线程. java 让线程 inactive 的方法是 wait(), wait(时间); 唤醒的方式是 notify, notifyAll,(必须是同一个对象), 或者 发出interupt 信号.

另外一个让线程暂时休眠的方法是 Thread.currentThread().sleep(时间). 让线程暂时休眠固定的时间, 倒是自动醒来, 不需要唤醒.

参考: Chapter 17. Threads and Locks

Struts2 学习笔记 2.3.x

All config files for struts2


Struts2 配置文件
web.xml -> filter dispatcher -> init framework
struts-default.xml -> struts.xml
struts-default.property -> struts.property

Interceptor -> Action -> Result
request(url) -> action class -> method -> return string -> result type
predefined result names[token] from com.opensymphony.xwork2.ActionSupport -> Action (Interface):
String SUCCESS = "success";
String NONE = "none";
String ERROR = "error";
String INPUT = "input";
String LOGIN = "login";

参考: http://struts.apache.org/release/2.3.x/docs/guides.html