结合多本著作和个人开发经验,整理Java多线程入门手册(2)

上一篇 / 下一篇  2023-02-03 10:42:28

  三种实现方式区别
  ·Java单继承的特性决定,使用实现接口的方式创建线程更灵活
  · Callable实现call方法有返回值和异常抛出,方便定位问题,配合FutureTask可以获取线程运算结果,而run方法没有返回值,没有异常抛出
  · 如果线程运行结束后不需要返回值,则推荐使用实现Runnable接口方式
  小贴士:有不少文章中写到【实现的方式更适合用来处理多个线程有共享数据的情况】,很多小伙伴也拿去背,这句话怎么看都不对吧,多线程共享数据不加锁,不同步怎么着也不能避免线程安全问题!
  线程开辟
  · 开辟线程需要通过Thread类创建对象
  · 启动线程需要Thread对象调用start方法
  · 线程的功能可以装在Thread类的run方法或者Runnable接口实现类的run方法类中
  · 线程开辟需要在另一个线程中开启,新开辟的线程称为子线程
  小贴士:对于Java应用程序java.exe来讲,至少会存在三个线程:
  main主线程
  gc垃圾回收线程
  异常处理线程,如果发生异常会影响主线程。
  线程状态
  线程的状态网上有 5种状态 和 6种状态 两个版本。
  五种状态版本:是基于现代操作系统线程状态角度解释的。
  新建:当一个Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建状态。
  就绪:处于新建状态的线程被start后,将进入线程队列等待CPU时间片,此时它已具备了运行的条件,只是没分配到CPU资源。
  运行:当就绪的线程被调度并获得CPU资源时,便进入运行状态,run方法定义了线程的操作和功能。
  阻塞:在某种特殊情况下,被人为挂起或执行输入输出操作时,让出CPU并临时终止自己的执行,进入阻塞状态。
  死亡:线程完成了它的全部工作或线程被提前强制性地中止或出现异常导致结束。
  在JDK5的时候Thread类中定义了一个State枚举类,其中定义了6种线程状态,这是Java官方定义的Java线程的6种状态
  1)NEW:处于NEW状态的线程此时尚未启动。只是通过new Thread()创建了线程对象,并未调用start()方法
  2)RUNNABLE:Java线程的 RUNNABLE 状态其实是包括了传统操作系统线程的 就绪(ready) 和 运行(running) 两个状态的。处于 RUNNABLE 状态的线程可能在 Java 虚拟机中运行,也有可能在等待 CPU 分配资源
  3)BLOCKED:阻塞状态。处于 BLOCKED 状态的线程正等待锁的释放以进入同步区,就好比你去食堂打饭,只有一个窗口你就得排队,等前边的人结束之后你完成打饭
  4)WAITING :等待状态。处于等待状态的线程变成 RUNNABLE 状态需要其他线程唤醒
  可以通过调用一下三个方法进入等待状态:
  ·Object.wait():使当前线程处于等待状态直到另一个线程唤醒它;
  · Thread.join():使当前线程等待另一个线程执行完毕之后再继续执行,底层调用的是 Object 实例的 wait() 方法;
  · LockSupport.park():除非获得调用许可,否则禁用当前线程进行线程调度
  5)TIMED_WAITING:超时等待状态。线程等待一个具体的时间,时间到后会被自动唤醒。
  调用如下方法会使线程进入超时等待状态:
  · Thread.sleep(long millis):使当前线程睡眠指定时间,sleep() 方法不会释放当前锁,但会让出 CPU,所以其他不需要争夺锁的线程可以获取 CPU 执行;
  · Object.wait(long timeout):线程休眠指定时间,等待期间可以通过 notify() / notifyAll() 唤醒;
  · Thread.join(long millis):等待当前线程最多执行 millis 毫秒,如果 millis 为 0,则会一直执行;
  · LockSupport.parkNanos(long nanos): 除非获得调用许可,否则禁用当前线程进行线程调度指定时间;
  · LockSupport.parkUntil(long deadline):同上,也是禁止线程进行调度指定时间;
  6)TERMINATED:终止状态。此时线程已执行完毕。
  其实等待和锁定状态可以被笼统的称为阻塞状态,就是停着不动了嘛,在回答面试题时建议回答6种状态版本,就是是JDK源码中定义的,一来有官方支持,二来证明咱看过一点源码。
  状态转换
  · 新建状态的线程调用start方法进入到运行状态
  · 运行状态线程如果遇到Object.wait()、Thread.join()或者LockSupport.park()方法则会放弃CPU执行权进入等待状态,这个装需要被唤醒之后才会再次进入就绪状态获得到CPU时间片进入运行状态
  · 运行状态的线程遇到Thread.sleep(long)、Object.wait(long)、Thread.join(long)等方法,也就是可以传入时间的,就会进入超时等待状态,达到时间之后就会自动进入就绪状态,当CPU执行就进入运行状态
  · 运行状态的线程如果被同步代码块或者同步方法包裹,执行时如果释放锁资源,就会进入阻塞状态或者叫锁定状态,只有再次获取到锁资源时才会进入就绪状态,等到CPU时间片后进入运行状态
  · 执行完的线程就会进入终止状态,线程结束。
  线程之间的状态转换可以参考下图:
  Thread类详解
  成员变量
  常量
  /**
   * The minimum priority that a thread can have.
   */
  public final static int MIN_PRIORITY = 1;
  /**
   * The default priority that is assigned to a thread.
   */
  public final static int NORM_PRIORITY = 5;
  /**
   * The maximum priority that a thread can have.
   */
  public final static int MAX_PRIORITY = 10;
  Thread构造方法
  从源码看出Thread类一共有9个构造方法,除第三个为default修饰【同包可用】,其他都是public
  Thread常用方法

TAG: Java java

 

评分:0

我来说两句

Open Toolbar