跳到主要内容

中文在线

1. 锁

1.1 按获取方式:

  • 悲观锁:假设总有线程冲突(如 synchronized、数据库行锁)。
  • 乐观锁:假设不会有冲突,更新前校验版本(如 CAS + version)。

1.2 Java 常用锁:

锁类型特点
synchronized内置锁,自动加解锁,重入
ReentrantLock可重入,灵活控制锁粒度
ReadWriteLock多读单写
StampedLock支持乐观读,适合高并发场景
SpinLock自旋等待,不阻塞线程
Semaphore信号量,限流控制
CountDownLatch多线程协作:等待计数归零
CyclicBarrier多线程协作:凑齐一批线程后执行

2. 线程的状态

线程生命周期中有 6 种状态:

状态说明
NEW新建线程对象,但未调用 start()
RUNNABLE可运行状态(可能正在运行或等待调度)
BLOCKED被阻塞,等待锁释放(如 synchronized 竞争)
WAITING无限期等待(如 Object.wait()
TIMED_WAITING有时间限制的等待(如 sleep(), join(timeout)
TERMINATED线程已结束

3. 线程会用到的关键字

✅ 常见的线程相关方法

  1. start():启动一个新线程,调用此方法后,线程的状态变为 Runnable,由操作系统的线程调度器来调度执行。

    Thread t = new Thread();
    t.start();
  2. sleep(long millis):使当前线程休眠指定的毫秒数,释放 CPU 资源,让其他线程有机会执行。

    Thread.sleep(1000); // 让当前线程休眠 1 秒
  3. join():当前线程等待指定线程执行完毕后再继续执行。常用于线程间的协作。

    thread.join(); // 当前线程等待该线程执行完成
  4. yield():当前线程放弃 CPU 资源,进入就绪状态,让其他相同优先级的线程有机会执行,通常用于调度策略优化。

    Thread.yield();
  5. interrupt():中断一个线程,通知线程停止当前执行。线程内部必须正确响应中断(通常通过抛出异常或检查中断状态)。

    thread.interrupt(); // 中断线程
  6. isAlive():检查线程是否已启动并正在运行。

    thread.isAlive(); // 判断线程是否存活
  7. setDaemon(boolean on):设置当前线程为守护线程,守护线程会在 JVM 退出时自动结束。

    thread.setDaemon(true); // 设置为守护线程
  8. getId():获取线程的唯一 ID。

    long id = thread.getId(); // 获取线程 ID
  9. getState():获取线程的当前状态(如 NEW、RUNNABLE、WAITING、BLOCKED)。

    Thread.State state = thread.getState(); // 获取线程状态
  10. currentThread():获取当前正在执行的线程的引用。

    Thread currentThread = Thread.currentThread(); // 获取当前线程

✅ 线程相关的关键字

  1. synchronized:用于同步代码块或方法,保证线程安全。确保一个时刻只有一个线程能够执行被 synchronized 修饰的代码。

    synchronized (obj) {
    // 只有一个线程可以执行这个代码块
    }
  2. volatile:保证变量的可见性,确保一个线程修改了该变量,其他线程能立即看到修改后的值。它不保证原子性。

    private volatile boolean flag;
  3. final:用于定义不可修改的常量,常用于线程安全的对象设计。

    final int MAX_THREADS = 10; // 常量
  4. ThreadLocal:为每个线程提供一个独立的变量副本,避免线程间共享数据,适合存储线程独立的数据(如用户会话信息等)。

    ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
  5. wait():线程等待,释放对象锁,直到其他线程唤醒它。通常与 notify()notifyAll() 一起使用。

    synchronized (obj) {
    obj.wait(); // 当前线程释放锁并等待
    }
  6. notify() / notifyAll():唤醒一个或所有等待该对象锁的线程。常与 wait() 一起使用,通常用于线程间的协调与通信。

    synchronized (obj) {
    obj.notify(); // 唤醒一个线程
    obj.notifyAll(); // 唤醒所有等待的线程
    }

4. B树和B+树区别

对比项B树B+树(MySQL 索引结构)
数据存储所有节点都存数据只有叶子节点存数据
查找效率查找时可能在中间节点结束查找一定在叶子节点,查询路径固定
区间查询效率较低叶子节点通过链表连接,支持范围查找高效
结构多路搜索树叶子节点链表 + 多路搜索树

5. 索引的底层数据结构

MySQL(InnoDB)的索引结构为 B+树,底层结构特点:

  • 高度平衡的多路搜索树,一般高度为 2~3,性能稳定。
  • 聚簇索引(主键索引):叶子节点存储整行数据。
  • 辅助索引(二级索引):叶子节点存储主键值,需要回表。

优点:

  • 范围查询性能高。
  • 每次 I/O 读取一个数据页(通常 16KB),减少磁盘访问次数。

6. OAuth2登录

OAuth2 是一个授权协议,常用于第三方登录(如 GitHub、微信登录):

🌐 四种授权方式(常见是授权码模式):

🎯 授权码模式(适用于 Web 服务端):

  1. 用户访问客户端,点击“使用第三方登录”。
  2. 跳转到授权服务器(如 GitHub),授权登录。
  3. 授权后返回授权码(code)。
  4. 客户端携带授权码换取 access_token。
  5. 使用 token 获取用户信息。

第三方登录使用的核心是 access_token + refresh_token

7. token和cookie的区别

维度TokenCookie
存储位置存储在浏览器本地(LocalStorage、SessionStorage)浏览器自动管理(内存或磁盘)
携带方式每次请求需前端手动放入 header自动随请求发送(如 Cookie Header)
跨域支持支持跨域访问默认不支持跨域,需配置 withCredentials
安全性需防止 XSS 攻击需防止 CSRF 攻击
适用场景前后端分离,移动端传统 Web 服务端渲染

实际项目中,经常使用 JWT(JSON Web Token) 存储用户身份信息,结合 Bearer Token 使用。