使用无返回值的线程

继承Thread类

实现Runnable接口

使用有返回值的线程

使用ExecutorService

  • 实现了Callable接口的类:该接口的call()方法可以返回一个值。
  • 使用ExecutorService来执行Callable任务:会返回一个Future对象。
  • 使用Future对象的get()方法来获取子线程完成后的返回值。

使用FutureTask

  • 创建实现了Callable接口的类或匿名类,定义返回值类型和计算逻辑。
  • 使用Callable实例创建一个FutureTask对象。
  • FutureTask对象作为Runnable传递给Thread对象,并启动线程。
  • 使用FutureTask对象的get()方法来获取执行结果。

线程的状态

  • NEW(新建状态)
    • 线程刚被创建,但还没有调用start()方法。在这个状态下,线程还没有开始执行。
  • RUNNABLE(可运行状态)
    • 线程已经启动,并且可以被调度执行。处于此状态的线程可能正在运行也可能正在等待CPU分配时间片。
    • 注意,在Java中,RUNNABLE状态包含了传统操作系统线程的“就绪”和“运行”两个状态。
  • BLOCKED(阻塞状态)
    • 线程因为尝试获取对象的监视器锁(即进入synchronized块或方法)而被阻塞,但该锁被其他线程持有。
    • 只有等待其他线程释放锁之后,被阻塞的线程才能获得锁并进入RUNNABLE状态。
  • WAITING(等待状态)
    • 线程因为调用以下方法之一而进入等待状态:
      • Object.wait()
      • Thread.join()
      • LockSupport.park()
    • 通过在该对象上调用以下方法唤醒:
      • Object.notify()
      • Object.notifyAll()
  • TIMED_WAITING(计时等待状态)
    • 线程因为调用以下方法之一并指定了超时时间而进入计时等待状态:
      • Thread.sleep(long millis)
      • Object.wait(long timeout)与WAITING状态下的Object.wait()区分开,这里是有超时参数的
      • Thread.join(long millis)与WAITING状态下的Thread.join()区分开,这里是有超时参数的
      • LockSupport.parkNanos(long nanos)
      • LockSupport.parkUntil(long deadline)
    • 在指定的等待时间过后,线程可能会自动返回到RUNNABLE状态;或者在等待期间,其他线程可以通过特定的唤醒方法使其返回到RUNNABLE状态。
  • TERMINATED(终止状态)
    • 线程的运行结束,这可能是因为run()方法执行完成,或者因为线程被中途中断或异常终止。
    • 处于这个状态的线程不能再次启动或恢复运行。
  • 状态流转图:

Java线程状态与操作系统线程状态对比

notion image

守护线程与普通线程的区别

用途

  • 普通线程:通常用于执行应用程序的核心功能和业务逻辑。
  • 守护线程:通常用于执行后台任务,如垃圾回收、内存管理等。它们不应该用于业务逻辑,因为它们可能在任何时候被JVM终止。

设置方式

  • 普通线程:在Java中,默认创建的线程都是普通线程。
  • 守护线程:可以通过调用Thread类的setDaemon(true)方法将线程设置为守护线程。这个调用需要在线程启动之前完成。

重要性

  • 普通线程:普通线程通常承载了应用程序的重要任务,不会被JVM随意终止。
  • 守护线程:守护线程的重要性较低,主要是为系统的其他部分服务,它们在所有普通线程都结束后会自动被终止。

生命周期

  • 普通线程:普通线程的运行不会影响JVM的停止。只有当所有普通线程都执行完毕后,JVM才会停止。
  • 守护线程:守护线程主要用于为其他线程(如普通线程)提供服务。当所有普通线程结束时,守护线程也会被JVM终止,不管它是否执行完毕。
  • 普通线程(userThread:打印5次消息,每次之间暂停1秒。这模拟了普通线程执行完毕后的自然结束。
  • 守护线程(daemonThread:尝试打印1000次消息,每次之间暂停100毫秒。但由于它是守护线程,当所有普通线程(这里只有userThread)执行完毕后,JVM会自动结束,这时守护线程也会随之终止。
 
Leetcode 2924. 找到冠军 IILeetcode 1379. 找出克隆二叉树中的相同节点
Loading...