目录
一、Thread 类
简单介绍一下 Thread 类:Thread 类是 JVM 用来管理线程的一个类,换句话说,每个线程都有一个唯一的 Thread 对象与之关联,也就是说 Java 代码中的 Thread 对象和操作系统中的线程是一一对应的。
二、常见的构造方法
方法 | 说明 |
---|---|
Thread() | 创建线程对象 |
Thread(Runnable target) | 使用 Runnable 对象创建线程对象 |
Thread(String name) | 创建线程对象,并命名 |
Thread(Runnable target, String name) | 使用 Runnable 对象创建线程对象,并命名 |
这里的后两个构造方法中的 name 属性,就是给线程起一个名字
public class ThreadTest1 {
public static void main(String[] args) {
Thread t = new Thread(() -> {
while (true) {
System.out.println("线程,启动!");
try {
Thread.sleep(1000);// 运行大此方法时,等待1000ms
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
}
}
此时启动线程之后,为了知道线程的名字,我们进入 jdk 的 bin 目录,找到jconsole.exe,打开它并选择我们刚刚运行的线程所在的进程,点击连接。
此时会弹出这样的窗口:
直接选择不安全链接即可。
这样,我们就可以看到,在我们没有手动给线程命名的情况下,线程的名字默认为 Thread-0。
我们在使用带有 name 属性的构造方法进行运行:
public class ThreadTest1 {
public static void main(String[] args) {
Thread t = new Thread(() -> {
while (true) {
System.out.println("线程,启动!");
try {
Thread.sleep(1000);// 运行大此方法时,等待1000ms
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "我的线程");
t.start();
}
}
此时再用 jconsole,就可以看到:
三、Thread 的几个常见属性
属性 | 获取方法 |
---|---|
ID | getId() |
名称 | getName() |
状态 | getState() |
优先级 | getPriority() |
是否后台线程 | isDaemon() |
是否存活 | isAlive() |
是否被中断 | isInterrupted() |
我们都知道,每个线程都有自己的 状态、优先级、上下文、记账信息,其中的状态和优先级是可以通过上面表格中的方法获得到的。
isDaemon()返回true,表示是后台线程,返回 false 表示为前台线程。这里的前台线程会阻止 java 进程结束,换句话说,必须得 java 进程中所有的前台线程都执行完,java 进程才能结束;而后台线程不阻止 java 进程结束,换句话说,哪怕后台线程还没执行完,java 进程该结束就结束了。创建的线程默认是前台的,可以通过 setDaemon() 设置成后台的。这个大概了解即可,就不进行代码演示了。
isAlive() 描述系统内核里的那个线程是否存活,线程的入口方法执行完毕,此时系统中的对应线程就没了,次哦是调用 isAlive() 就会返回 false。
public class ThreadTest2 {
public static void main(String[] args) {
Thread t = new Thread(() -> {
System.out.println("t, 启动!");
});
t.start();
try {
// 上面的 t 线程没有任何的循环和 sleep(),意味着代码会迅速执行完毕
// main 线程如果 sleep 结束,此时的 t 基本上就是已经执行完了的状态
// 此时虽然 t 对象还在,但是在系统中对应的线程已经结束了。
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(t.isAlive());
}
}
但是需要注意的是,此时虽然返回的是false,不代表 100% 就是 false,代码中的注释我是这么说的:“基本上就是已经执行完了的状态”,我说的是基本上,因为可能出现极端情况,使得主线程 sleep 结束了,t 线程仍然没有去 CPU 上执行,虽然概率极低。系统对于线程的调度是随机的,假设我们的机器上面存在很多的进程和线程,此时 CPU 调度一圈,消耗的时间可能就比较长,此时就可能导致某个线程隔了很久也没有调度上去,这个可能大多数人都遇到过这种情况:某些时候,电脑卡了,点击某个窗口,提示“未响应”,让我们选择等待还是结束进程。
中断一个线程:
中断一个线程就是让一个线程停下来。本质上讲,让一个线程终止,就是让该线程的入口方法执行完毕(不论是异常还是正常)。有如下几种方法:
- 给线程中设定一个结束标志位
public class ThreadTest3 {
public static boolean isQuit = false;
public static void main(String[