LeetCode717. 1 比特与 2 比特字符
717. 1 比特与 2 比特字符题目描述:有两种特殊字符: 第一种字符可以用一比特 0 表示 第二种字符可以用两比特(10 或 11)表示给你一个以 0 结尾的二进制数组 bits ,如果最后一个字符必须是一个一比特字符,则返回 true 。 示例 1: 输入: bits = [1, 0, 0] 输出: true 解释: 唯一的解码方式是将其解析为一个两比特字符和一个一比特字符。所以最后一个字符是一比特字符。 示例 2: 输入: bits = [1,1,1,0]输出: false解释: 唯一的解码方式是将其解析为两比特字符和两比特字符。所以最后一个字符不是一比特字符。 提示: 1 <= bits.length <= 1000 bits[i] 为 0 或 1 思路: 思维题,倒序判断最后一段1奇偶性,最后一个0被占用了,一旦构成01就是不合法的最后一段1为奇数则一定不合法最后一段1为偶数则一定合法这个可以枚举验证一下 代码:1234567891011121314class Solution { public boolea...
JUC 并发工具类
一、ReentranLock工具类Java官方在早期jdk1.5版本就引入了ReentranLock并发工具类,这是一种可重入的独占锁(排它锁),它允许同一个线程多次获取同一个锁而不会被阻塞。相比synchronized,它提供了更灵活的控制能力,如可中断锁、可超时获取锁、条件变量等,用于解决高并发场景下需要灵活控制的业务场景。下面是使用ReentranLock的演示代码 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556import java.util.concurrent.locks.ReentrantLock;/** * ReentrantLock使用演示:多线程操作共享资源的线程安全控制 */public class ReentrantLockDemo { // 创建可重入锁实例(默认非公平锁,传入true可创建公平锁) private static final ReentrantLock loc...
ThreadLocal、CAS、Atomic及并发安全
一、ThreadLocal1. 为什么要有ThreadLocal ?ThreadLocal的核心作用是:让变量成为“线程私有”的副本,每个线程操作自己的那份,互不干扰,以此避免多线程共享变量的安全问题;同时,线程内的变量能在任意方法里直接获取,不用一层层传参数,简化代码。 2. ThreadLocal的使用ThreadLocal的使用非常简单,只有下面四个方法:为了性能上的优化,Thread内部设置了一个ThreadLocal.ThreadLocalMap的成员变量。这样每个线程访问自己内部的变量可以无需传参即可跨方法传递使用。 void set(Object value) public Object get() public void remove() protected Object initialValue() 3. ThreadLocal的实现1.结构设计ThreadLocal的内部实现非常有意思,每个Thread内部设置了一个ThreadLocal.ThreadLocalMap的成员变量。ThreadLocalMap内部用来存储值是一个Entry数组,可以看作是一个...
多线程并发、等待及通知机制
1. 基础概念进程进程 = 程序 + 执行 进程是系统分配资源的基本单位(内存、CPU时间片)进程是用来实现多进程并发执行的一个实体,实现对CPU的虚拟化,让每个进程感觉都拥有一个CPU,核心技术就是上下文切换和进程调度。进程是正在运行的程序的实例。进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。进程是执行中的程序,除了可执行代码外还包含进程的活动信息和数据,比如用来存放函数变量、局部变量、返回值的用户栈,存放进程相关数据的数据段,内核中进程间切换的内核栈,动态分配的堆。 早期操作系统程序都是单个运行的,CPU利用率低下,为了提高CPU的利用率,加载多个程序到内存并发运行,在单核CPU中这种属于伪并发。其实在同一时间只运行一个程序 线程通常在一个进程中可以包含若干个线程,它们可以利用进程所拥有的资源,在引入线程的操作系统中,通常都是把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位,由于线程比进程更小,基本上不拥有系统资源,故对它的调度...
深入理解 Sentinel 限流组件推模式实现
在微服务架构中,流量控制是保障系统稳定性的核心手段,Sentinel 作为主流限流组件,其规则同步模式直接影响分布式环境下的可用性。本文将聚焦 Sentinel 推模式的实现细节,对比拉模式的局限性,并补充多种主流实现方案,为线上分布式场景提供实践参考。 一、Sentinel 规则同步的两种核心模式在正式讲解推模式前,需先明确 Sentinel 规则同步的两种基础模式:拉模式(Pull Mode) 与 推模式(Push Mode),二者的核心差异在于规则的主动方与持久化方式。 1.1 拉模式:本地文件驱动的“被动同步”拉模式是 Sentinel 最基础的规则同步方式,核心依赖本地文件存储,实现逻辑如下: 客户端通过定时任务(默认间隔 3 秒)主动读取本地配置文件(如 JSON 格式); 若文件内容变更,客户端更新本地规则缓存,生效限流逻辑; 服务端(或运维人员)需手动向每个客户端节点推送文件,才能实现规则更新。 局限性: 无法实现“一策多节点”:规则仅对单个节点生效,若微服务部署 10 个实例,需手动更新 10 次配置文件; 无持久化保障:本地文件易丢失,且无法追溯规则变更...
Tomcat的IO模型与性能调优
1. Tomcat的I/O模型1.1 Linux I/O模型I/O要解决什么问题?I/O本质上是在解决在计算机内存与外部设备之间拷贝数据的过程 程序通过CPU向外部设备发出读指令,数据从外部设备拷贝至内存需要一段时间,这段时间CPU就没事情做了,程序此时有两种选择: 让出CPU资源,CPU执行其他任务 继续使用CPU轮询数据是否拷贝完成 采取的具体策略就是不同I/O模型要解决的问题 以网络数据读取为例分析,会涉及两个对象,一个是调用I/O操作的用户线程,另一个是操作系统内核。一个进程的地址空间分为用户空间和内核空间,基于安全上的考虑,用户程序只能访问用户空间,内核程序可以访问整个进程空间,只有内核可以直接访问各种硬件资源,比如磁盘和网卡。 当用户线程发起I/O调用后,网络数据读取操作会经历两个步骤: 数据准备阶段:用户线程等待内核将数据从网卡拷贝到内核空间 数据拷贝阶段:内核将数据从内核空间拷贝到用户空间(用户进程的缓冲区) Linux的I/O模型分类 同步阻塞I/...
Tomcat类加载机制与热部署原理详解
1.Tomcat类加载机制详解1.1 JVM类加载器Java中有3种类加载器,当然你也可以自定义类加载器 引导类加载器(启动类加载器):负责加载支撑JVM运行的位于JRE的lib目录下的核心类库,比如rt.jar、charsets.jar 扩展类加载器:负责加载支撑JVM运行的JRE的lib目录下ext扩展目录中的核心jar包 应用程序类加载器(系统类加载器):负责ClassPath路径下的类包,主要就是加载你自己写的类 自定义类加载器:自己实现,负责加载自定义路径下的类包1234567891011121314151617public class ClassLoaderDemo{ public static void main(String[] args){ // BootStrapClassLoader c/c++实现,java层面是获取不到的,会输出null System.out.println(ReentrantLock.class.getClassLoader()); // ExtClassLoader System.out...
Tomcat 整体结构以及设计源码分析
1. Tomcat是什么?Tomcat 是一款开源的 Java Web 服务器 + Servlet 容器,由 Apache 软件基金会开发维护,主要用于部署和运行 Java Web 应用程序(如基于 Servlet、JSP、Spring MVC 等技术的应用)。它是 Java 生态中最流行的 Web 容器之一,兼具轻量性、稳定性和易扩展性,广泛用于开发和生产环境。 123456789apache-tomcat-10.0.0/├── bin/ # 脚本与可执行文件目录├── conf/ # 配置文件目录├── lib/ # 核心依赖库目录├── webapps/ # Web 应用部署目录├── logs/ # 日志文件目录├── temp/ # 临时文件目录├── work/ # JSP 编译缓存目录└── LICENSE、NOTICE 等 # 许可证和说明文件 2. WEB应用部...
G1 垃圾收集器学习笔记
G1垃圾收集器学习笔记2025-09-23一、G1垃圾收集器概述G1(Garbage-First)是Java 9默认的垃圾收集器,核心特性如下: 取消物理分代:将内存划分为2048个逻辑Region(默认值) 动态分区管理:年轻代/老年代区域可相互转化 巨型对象处理:新增Humongous区存储超Region 50%的大对象 二、内存管理机制1. 内存分区 逻辑分区:保留年轻代(Eden/Survivor)、老年代概念 物理结构: 默认2048个Region(通过-XX:G1HeapRegionSize调整) 年轻代初始占比5%(动态调整,上限60%) Eden:Survivor默认比例8:1:1 2. 特殊区域 Humongous区: 存储超过Region 50%的大对象 若对象超过单个Region大小,会被分割存储于多个连续Region 三、垃圾回收流程G1回收分为四个阶段: 初始标记(Stop The World) 标记GC Roots直接引用对象 并发标记(Concurrent) 与...
Seata AT 模式与 XA 模式的区别
1. 模式区别 AT 模式:生成的是数据源代理(DataSource Proxy),通过代理拦截 SQL 执行,无需额外配置默认模式(Seata 默认支持 AT 模式),而非“数据库动态代理”(表述更精准)。 XA 模式:生成的是 XA 数据源代理(XADataSource Proxy),需在 YAML 中显式配置 seata.tx-mode=XA(而非仅“配置默认模式为 XA”),且依赖数据库原生 XA 协议支持(如 MySQL、Oracle 的 XA 事务能力)。 2. AT 模式流程 第一步会申请全局事务 ID(XID)(需明确“全局”,与分支事务 ID 区分)。 基于原有分布式服务调用逻辑扩展,实现异常后的自动回滚(而非“自动补偿”)——补偿逻辑通过 Undo Log 反向生成 SQL 实现,需明确概念。 事务开始前:申请 XID 并存储到 ThreadLocal(Seata 内部通过 RootContext 管理 XID,MDC 通常用于日志打印携带 XID,非核心存储位置,修正存储载体);往 TC(事务协调器)的全局事务表(global_table)插入记录;将数据...
