目录
(3)使用Thread类内置的标志位 isInterrupted()
一、认识线程-Thread类
一个线程就是一个“执行流”。每个线程都可以按照顺序执行自己的代码,而多个线程可以 "同时" 执行多份代码。线程本身是操作系统中的概念。操作系统内核实现了线程这样的机制,并且对用户层提供了一些 API 供用户使用(例如 Linux 的 pthread 库)。而Java 标准库中 Thread 类可以视为是对操作系统提供的 API 进行了进一步的抽象和封装。
Thread 类是 JVM 用来管理线程的一个类。在Java中,每个线程执行流都是通过Thread类的对象来描述的。JVM 会将这些 Thread 对象组织起来,用于线程调度,线程管理。
使用Thread类,我们可以创建和管理多个线程,并控制它们的执行顺序、优先级、暂停、恢复等。
1、Thread类的常见构造方法
Thread() :无参的构造方法。
Thread(Runnable target) :Runnable是一个接口类型。该构造方法需要一个Runnable类型的target参数。具体如何使用,在下文“创建线程”的部分会详细说明。
Thread(String name) / Thread(Runnable target, String name):在创建线程的同时自定义一个线程对象名。这个操作相当于是给线程起了一个别名,方便后续查找辨认该线程,不影响程序的正常运行。不指定名称,系统也会给线程一个默认的名称。我们可以用 jconsole 工具来查看Java程序中的线程:
先用Java代码创建两个线程(如何创建线程仍然会在下文说明),并运行程序:
在 jconsole 中可以看到:
这里的Thread-0,Thread-1就是系统默认给我们线程的命名。
此时,如果我们给线程 t1 指定一个name为"hello_t1",再次用 jconsole 查看线程情况:
可见此时,t1 的名称就显示为我们自定义的"hello_t1"了。而 t2 未自定义命名,因此还是默认的名称。但是,起名只是方便标识,无论名称如何,都不影响程序的正常运行。
2、Thread 的几个常见属性
- ID 是线程的唯一标识,不同线程不会重复。
System.out.println(t1.getId());
System.out.println(t2.getId());
- 名称就是我们上面提到的线程的命名,通常各种调试工具会用到。
- 状态表示线程当前所处的一个情况,下文中我们会进一步说明。
- 是否存活,可以简单地理解为 :run 方法是否运行结束了
- 优先级高的线程理论上来说更容易被调度到,但并不绝对。因为优先级只是“建议”性质的,不是强制性质的。优先级高意味着“建议”操作系统优先调度某线程,但实际到底要不要优先调度,还是取决于操作系统。
- 线程分后台线程和前台线程。关于后台线程:JVM会在一个进程的所有非后台线程(也就是前台线程)结束后,才会结束运行。创建的线程默认是前台线程,main线程也是一个前台线程。
Daemon 表示一个后台进程(也叫守护进程)。.isDaemon()方法可以获得线程是前台进程还是后台进程。true表示是后台进程,false表示是前台进程。
.setDaemon()方法可以手动设置一个线程为前台线程或后台线程。具体演示如下:

如果我们将 t1.setDaemon(true) 语句删除,会怎样呢?此时t1就不再是后台进程,而是一个前台进程了,只有等到t1线程也结束,整个进程才会结束。但由于t1中有死循环,因此进程不会结束。

二、Thread类的基本用法
1、创建线程
方法一 继承 Thread 类
通过继承 Thread 类的方式来创建线程,主要分为 4 步:
- 自定义类 MyThread 类 继承 Thread类。
- 在 MyThread类 中重写 run() 入口方法。
- 在 main 中创建(new)MyThread类 的实例 t 。
- 通过 t 调用 start() 方法,启动线程。
具体代码演示如下:
// 1、通过继承Thread类来创建线程
class MyThread extends Thread {
// 2、重写 run() 方法
@Override
public void run() {
System.out.println("i am t!");
}
}
public class Test {
public static void main(String[] args) {
// 3、创建 MyThread 实例
MyThread t = new MyThread();
// 4、调用 实例t 的 start() 方法
t.