-
Selector不能直接支撑万级连接,因其仅为事件分发开关而非自动扩容线程池;真正决定并发能力的是SelectionKey的有效管理、及时取消、避免select阻塞或空轮询,以及IO与业务逻辑严格分离。
-
TLAB是什么,为什么每个线程要自己分一块小内存TLAB(ThreadLocalAllocationBuffer)是JVM在堆内存中为每个线程单独划出的一小块连续空间,专供该线程快速分配对象。它不是独立于堆之外的区域,而是Eden区内的“私有子区”。没有TLAB时,所有线程都要竞争Eden的公共指针(如top),频繁加锁或CAS,成为性能瓶颈;启用后,线程直接在自己的缓冲区里挪动本地指针,几乎无竞争。常见错误现象:GClogs里看到大量TLABwaste或TLA
-
?extendsT只读不可写,因编译器无法确定具体子类型,添加非null元素会破坏类型安全;仅允许get()等读操作,可传null;适用于只读方法参数,提升API兼容性与安全性。
-
Collections.checkedCollection()提供运行时类型安全包装,仅对写操作检查元素类型,不验证已有元素或读操作返回值;需传入非空原始集合和具体类型Class,适用于API边界防护等场景。
-
MetaspaceSize和MaxMetaspaceSize应设为相等以避免动态扩容引发的频繁FullGC和OOM;需结合服务复杂度合理设定值(128m~1g),并优先排查类加载器泄漏,而非盲目调参。
-
不能直接在@Transactional方法里sendMQ(),因为事务提交发生在方法返回后,此时sendMQ()执行时数据库事务尚未真正落盘,导致消费者查不到数据;应使用@TransactionalEventListener(phase=TransactionPhase.AFTER_COMMIT)确保事务已刷盘后再发消息。
-
Collections.synchronizedList()不能真正解决并发修改问题,因其仅保证单个操作原子性,不保护复合操作(如遍历删除、检查后添加),迭代器未加锁导致ConcurrentModificationException频发,且keySet等视图非线程安全。
-
final字段必须在声明或构造方法中初始化且仅一次,编译器编译期强制检查并报错,禁止运行时修改;静态final需在静态块或声明时初始化,实例final绑定构造过程。
-
优先选择组合而非继承,因其更利于封装、解耦和测试;仅当满足is-a关系、父类明确支持继承且无易变逻辑时才用继承。
-
本地内部类适合封装一次性、轻量且与当前逻辑强耦合的辅助对象;它有明确类名,支持多方法、构造器、字段、重载、多接口实现及多次实例化,可读性优于匿名类和Lambda。
-
Map.compute()是Java8引入的原子性键值更新方法,接收key和BiFunction(k,v)→newV,支持累加、拼接、条件更新及删除(返回null),v为当前值(含null),无法区分键不存在与值为null。
-
Collections.shuffle()基于Fisher–Yates算法原地洗牌,要求可变且支持随机访问的List(如ArrayList),不支持LinkedList或不可变集合;需注意线程安全、可重现性(传入自定义Random)、避免对Arrays.asList()结果误增删;Collections.reverse()同样原地反转、无返回值,作用于subList会影响原列表,组合操作顺序影响结果,不可变集合须先转为ArrayList再调用。
-
sealed关键字不支持“只允许指定子类继承”的白名单控制,仅提供彻底禁止继承(类)或终止重写(成员)的黑名单机制;需通过internal构造器、程序集边界或工厂模式等设计手段实现受限继承。
-
Charset.forName()不抛UnsupportedEncodingException,而是抛IllegalArgumentException;真正抛该异常的是String.getBytes(String)等老式API;推荐用StandardCharsets.UTF_8或先调用Charset.isSupported()校验。
-
Java内存划分为栈和堆,核心是兼顾执行效率与灵活性:栈管理方法执行(存基本类型、引用、调用现场),生命周期短、释放快;堆管理对象存储(动态分配、GC回收),生命周期长、支持共享。