零碎笔记(六)

本文深入探讨了Java中的关键概念和技术,包括线程栈管理、HashMap的工作原理、随机数生成器的选择及线程中断的正确处理方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       防止JVM吃异常堆栈的参数 -XX:-OmitStackTraceInFastThrow

       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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值