防止JVM吃异常堆栈的参数 -XX:-OmitStackTraceInFastThrow
Java将为每个线程维护一个堆栈,堆栈里将为每个方法保存一个栈帧,栈帧代表了一个方法的运行状态,也就是方法栈,最后一个为当前运行的栈帧。
那么每一次方法调用会涉及:
1.为新调用方法的生成一个栈帧
2.保存当前方法的栈帧状态
3.栈帧上下文切换,切换到最新的方法栈帧。
递归实现将导致栈内存的消耗(往往需要调整Xss参数)以及栈帧创建和切换的性能开销,最终大大的影响效率。
所以想提升算法效率,不要使用递归实现。
volatile修饰的数组只针对数组的引用具有volatile的语义,而不是它的元素。
静态内部类可以有静态成员(方法,属性),而非静态内部类则不能有静态成员(方法,属性)。
静态内部类只能够访问外部类的静态成员,而非静态内部类则可以访问外部类的所有成员(方法,属性)。
实例化一个非静态的内部类:
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
TimeZone.getTimeZone("GMT")
TimeZone.getTimeZone("GMT+8")// Asia/Shanghai即GMT+8
JVMMemory JVM内存
ReservedOsMemory 保留的操作系统内存
ThreadStackSize 线程栈的大小
在java语言里, 当你创建一个线程的时候,虚拟机会在JVM内存创建一个Thread对象同时创建一个操作系统线程,而这个系统线程的内存用的不是JVMMemory,而是系统中剩下的内存(MaxProcessMemory - JVMMemory - ReservedOsMemory)。
由公式得出结论:JVM内存越多,那么能创建的线程越少,越容易发生java.lang.OutOfMemoryError: unable to create new native thread。
初始化时HashMap的容量总是2的n次方,即底层数组的长度总是为2的n次方。当length总是2的n次方时,length - 1得到的二进制数的除高位外每个位上的值都为1,那么h & (length - 1)运算等价于对length取模,也就是h % length,但是&比%具有更高的效率。
举个例子来说明:数组长度为0b1000(16), hash值为0b0101(9), &运算后的结果h & (length - 1) = 0b0101 & 0b0111 = 0b0101 = 9 = 9 % 16,再假设hash值为0b1001(17),h & (length - 1) = 0b0101 & 0b1001 = 0b0001 = 1 = 17 % 16。
能够生成随机数的相关类有三种Random、ThreadLocalRandom、SecureRandom。Random即java.util.Random,ThreadLocalRandom即java.util.concurrent.ThreadLocalRandom,SecureRandom即java.security.SecureRandom。
Random是线程安全的,但是多线程下可能性能比较低(http://stackoverflow.com/questions/5819638/is-random-class-thread-safe)。但是ThreadLocalRandom要比Random高效,Random用了很多CAS的类,ThreadLocalRandom根本没有用到。
产生高强度的随机数,有两个重要的因素:种子和算法。当然算法是可以有很多的,但是如何选择种子是非常关键的因素。如Random,它的种子是 System.currentTimeMillis(),所以它的随机数都是可预测的。在安全性要求比较高的场合,应当使用SecureRandom。
Thread.interrupted方法误用
正确的写法:
在静态变量初始化时创建线程时需要注意thread会从它的父线程(即当前线程)中继承各种属性. 比如context classloader, threadlocal以及其他的安全属性(访问权限).如果需要控制线程的属性, 最好的做法就是将其初始化操作放在一个静态方法中, 这样初始化将由它的调用者来决定.
twitter利用zookeeper实现了一个全局ID生成的服务snowflake,https://github.com/twitter/snowflake,可以生成全局唯一的64bit ID。
生成的ID的构成:
时间--用前面41 bit来表示时间,精确到毫秒,可以表示69年的数据
机器ID--用10 bit来表示,也就是说可以部署1024台机器
序列数--用12 bit来表示,意味着每台机器,每毫秒最多可以生成4096个ID
Java将为每个线程维护一个堆栈,堆栈里将为每个方法保存一个栈帧,栈帧代表了一个方法的运行状态,也就是方法栈,最后一个为当前运行的栈帧。
那么每一次方法调用会涉及:
1.为新调用方法的生成一个栈帧
2.保存当前方法的栈帧状态
3.栈帧上下文切换,切换到最新的方法栈帧。
递归实现将导致栈内存的消耗(往往需要调整Xss参数)以及栈帧创建和切换的性能开销,最终大大的影响效率。
所以想提升算法效率,不要使用递归实现。
volatile修饰的数组只针对数组的引用具有volatile的语义,而不是它的元素。
静态内部类可以有静态成员(方法,属性),而非静态内部类则不能有静态成员(方法,属性)。
静态内部类只能够访问外部类的静态成员,而非静态内部类则可以访问外部类的所有成员(方法,属性)。
实例化一个非静态的内部类:
//生成一个外部类对象实例
OutClassTest oc1 = new OutClassTest();
//通过外部类的对象实例生成内部类对象
OutClassTest.InnerClass no_static_inner = oc1.new InnerClass();
实例化一个静态内部类的方法://不依赖于外部类的实例,直接实例化内部类对象
OutClassTest.InnerStaticClass inner = new OutClassTest.InnerStaticClass();
//调用内部静态类的方法或静态变量,通过类名直接调用
OutClassTest.InnerStaticClass.static_value
OutClassTest.InnerStaticClass.getMessage()
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
TimeZone.getTimeZone("GMT")
TimeZone.getTimeZone("GMT+8")// Asia/Shanghai即GMT+8
Number of threads = (MaxProcessMemory - JVMMemory - ReservedOsMemory) / ThreadStackSize
其中:MaxProcessMemory 指的是一个进程的最大内存JVMMemory JVM内存
ReservedOsMemory 保留的操作系统内存
ThreadStackSize 线程栈的大小
在java语言里, 当你创建一个线程的时候,虚拟机会在JVM内存创建一个Thread对象同时创建一个操作系统线程,而这个系统线程的内存用的不是JVMMemory,而是系统中剩下的内存(MaxProcessMemory - JVMMemory - ReservedOsMemory)。
由公式得出结论:JVM内存越多,那么能创建的线程越少,越容易发生java.lang.OutOfMemoryError: unable to create new native thread。
初始化时HashMap的容量总是2的n次方,即底层数组的长度总是为2的n次方。当length总是2的n次方时,length - 1得到的二进制数的除高位外每个位上的值都为1,那么h & (length - 1)运算等价于对length取模,也就是h % length,但是&比%具有更高的效率。
举个例子来说明:数组长度为0b1000(16), hash值为0b0101(9), &运算后的结果h & (length - 1) = 0b0101 & 0b0111 = 0b0101 = 9 = 9 % 16,再假设hash值为0b1001(17),h & (length - 1) = 0b0101 & 0b1001 = 0b0001 = 1 = 17 % 16。
能够生成随机数的相关类有三种Random、ThreadLocalRandom、SecureRandom。Random即java.util.Random,ThreadLocalRandom即java.util.concurrent.ThreadLocalRandom,SecureRandom即java.security.SecureRandom。
Random是线程安全的,但是多线程下可能性能比较低(http://stackoverflow.com/questions/5819638/is-random-class-thread-safe)。但是ThreadLocalRandom要比Random高效,Random用了很多CAS的类,ThreadLocalRandom根本没有用到。
产生高强度的随机数,有两个重要的因素:种子和算法。当然算法是可以有很多的,但是如何选择种子是非常关键的因素。如Random,它的种子是 System.currentTimeMillis(),所以它的随机数都是可预测的。在安全性要求比较高的场合,应当使用SecureRandom。
Thread.interrupted方法误用
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// ok
}
…
while (true) {
if (Thread.interrupted())
break;
}
这里主要是interrupted静态方法除了返回当前线程的中断状态, 还会将当前线程状态复位.正确的写法:
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
…
while (true) {
if (Thread.currentThread().isInterrupted())
break;
}
在静态变量初始化时创建线程时需要注意thread会从它的父线程(即当前线程)中继承各种属性. 比如context classloader, threadlocal以及其他的安全属性(访问权限).如果需要控制线程的属性, 最好的做法就是将其初始化操作放在一个静态方法中, 这样初始化将由它的调用者来决定.
twitter利用zookeeper实现了一个全局ID生成的服务snowflake,https://github.com/twitter/snowflake,可以生成全局唯一的64bit ID。
生成的ID的构成:
时间--用前面41 bit来表示时间,精确到毫秒,可以表示69年的数据
机器ID--用10 bit来表示,也就是说可以部署1024台机器
序列数--用12 bit来表示,意味着每台机器,每毫秒最多可以生成4096个ID