0%

Thread

1. 线程状态

  • NEW
  • RUNABLE
  • BLOCKED
  • WAITING
  • TIMED_WAITING
  • TERMINATED

1.1. WAITING vs BLOCKED

WAITING 状态是线程已经分配到 CPU 时间, 但是由于需要等待事件发生, 所以主动释放 CPU, 直到事件完成后调用被唤醒;
BLOCKED 状态是线程想到获得 CPU 时间, 但是没有获得锁, 所以轮不到, 进入 BLOCKED 状态;

2. API

  • start
    开启新线程, 等待 CPU 调用.

  • run
    不要使用 run 开启新线程, 直接调用 Thread.run() 只会在当前线程中, 串行执行 run 的代码.

  • stop
    立即终止线程, 已废弃.
    暴力终止, 假如线程工作到一半被终止, 可能会引起数据不一致等问题.

  • sleep
    线程进入 TIME_WAITING 状态.

  • interrupt
    中断线程.
    线程不会立即让线程退出, 而是给线程发送一个通知, 告知目标线程, 有人希望你退出; 线程收到通知后, 自行决定如何处理.

  • wait & notify
    线程等待和唤醒.
    线程中, 如果调用了 obj.wait() 方法, 那么线程就会停止继续执行, 进入 WAIT 状态, 直到有其他线程调用 obj.notify() 或 obj.notifyAll() 方法唤醒.

    wait 和 notify 方法都必须包含在对应的 synchronized 块中, 都必须先获得目标对象的监视器.

  • suspend & resume
    线程挂起和继续执行, 已废弃.
    线程调用 suspend 导致线程暂停的同时, 并不会释放任何锁资源. 其他线程想要访问被它占用的锁资源时, 都会受到影响, 无法正常继续运行, 直到 对应线程上调用 resume.

    resume 方法必须在 suspend 方法后面执行, 如果意外的在 suspend 前面执行了, 可能会导致被挂起的线程继续执行, 而导致整个系统无法正常工作.

  • join & yield
    join 会阻塞当前线程, 直到目标线程执行完毕. 如果给出最大等待时间, 在超出时间范围后继续执行.

    join 本质上是让调用线程 wait 在当前线程对象实例上. 在线程执行完成后, 被等待的线程在退出前调用 notifyAll 通知所有等待线程继续执行. 因此, 在开发中, 不要在 Thread 对象上使用类似 wait 或者 notify 等方法, 可能会影响系统 API 工作.

    yield 会让出 CPU, 表示当前线程不执行了. 如果觉得一个线程不那么重要, 或者优先级比较低, 而且害怕它占用太多 CPU 资源, 那么可以在适当的适合调用 yield, 给其他重要线程更多的工作机会.

3. 守护线程 Daemon

守护线程表示该线程提供系统性的服务, 比如垃圾回收线程, JIT 线程.
与之对应的是用户线程, 可以认为是系统的工作线程, 它会完成这个常旭应该完成的业务工作.
当用户线程全部结束时, 意味着这个程序实际上无事可做了, 守护线程要守护的对象已经没有了, 整个程序可以结束了.

4. 线程同步方式

  • 自旋 CAS, 参考 ConcurrentHashMap 中的 get() 方法