本文主要介绍 Java 的 Thread 类一些用法。
private static class NukixThread extends Thread {
public NukixThread(String name) {
super(name);
}
@Override
public void run() {
System.out.println("线程 ID: " + getId() + ", 线程名称: " + getName());
}
}
isAlive: 判断线程是否存活。
sleep: 使线程休眠指定的时间(毫秒)。
interrupt: 中断线程的休眠状态, 比如令 sleep 抛出 InterruptedException 的异常。
isInterrupted: 判断线程是否被中断。
NukixThread A = new NukixThread("A") {
@Override
public void run() {
super.run();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("A 执行结束");
}
};
A.start();
NukixThread B = new NukixThread("B") {
@Override
public void run() {
super.run();
for (int i = 0; i < 2; i++) {
// A.interrupt();
System.out.println("A.isAlive: " + A.isAlive() + ", A.isInterrupted: " + A.isInterrupted());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("B 执行结束");
}
};
B.start();
线程 ID: 14, 线程名称: A
线程 ID: 15, 线程名称: B
A.isAlive: true, A.isInterrupted: false
A 执行结束
A.isAlive: false, A.isInterrupted: false
B 执行结束
当上面代码 A.interrupt(); 取消注释结果输出
java.lang.InterruptedException: sleep interrupted
线程 ID: 14, 线程名称: A
线程 ID: 15, 线程名称: B
A.isAlive: true, A.isInterrupted: false
at java.base/java.lang.Thread.sleep(Native Method)
at demo2.Main1$1.run(Main1.java:19)
A 执行结束
A.isAlive: false, A.isInterrupted: true
B 执行结束
wait: 使当前线程进入等待状态, 并且让出锁, 需要通过 notify 或者 notifyAll 进行唤醒。
notify: 唤醒正在等待的一个线程。
notifyAll: 唤醒正在等待的所有线程。
private static final Object lock = new Object();
private static int count = 0;
public static void main(String[] args) throws Exception {
NukixThread A = new NukixThread("A") {
@Override
public void run() {
super.run();
for (int i = 0; i < 3; i++) {
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(getName() + ": " + count++);
synchronized (lock) {
lock.notify();
}
}
System.out.println("A 执行结束");
}
};
NukixThread B = new NukixThread("B") {
@Override
public void run() {
super.run();
for (int i = 0; i < 3; i++) {
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(getName() + ": " + count++);
synchronized (lock) {
lock.notify();
}
}
System.out.println("B 执行结束");
}
};
NukixThread C = new NukixThread("C") {
@Override
public void run() {
super.run();
for (int i = 0; i < 3; i++) {
System.out.println(getName() + ": " + count++);
synchronized (lock) {
lock.notify();
}
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("C 执行结束");
}
};
A.start();
B.start();
C.start();
}
线程 ID: 14, 线程名称: A
线程 ID: 15, 线程名称: B
线程 ID: 16, 线程名称: C
C: 0
A: 1
B: 2
C: 3
A: 4
B: 5
C: 6
A: 7
A 执行结束
B: 8
B 执行结束
C 执行结束
从输出结果可以看出使用 notify 线程按照我们设定的 C->A->B 的顺序执行。 当我们把所有 notify 改成 notifyAll 会输出
线程 ID: 14, 线程名称: A
线程 ID: 16, 线程名称: C
线程 ID: 15, 线程名称: B
C: 0
A: 1
C: 2
B: 3
A: 4
C: 5
B: 6
A: 7
A 执行结束
C 执行结束
B: 8
B 执行结束
执行顺序会发生改变, 因为所有等待中的线程都被唤醒了。
join: 等待指定线程终止后继续运行。
NukixThread B = new NukixThread("B") {
@Override
public void run() {
super.run();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("B 执行结束");
}
};
NukixThread A = new NukixThread("A") {
@Override
public void run() {
super.run();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
B.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("A 执行结束");
}
};
A.start();
B.start();
线程 ID: 15, 线程名称: A
线程 ID: 14, 线程名称: B
B 执行结束
A 执行结束
A 等待1秒, B 等待5秒, 正常情况应该 A 先结束。 但执行 B.join() 后, A 需要等到 B 执行完毕后才能继续执行。
setDaemon: 设置线程为守护线程。
isDaemon: 判断线程是否守护线程。
NukixThread B = new NukixThread("B") {
@Override
public void run() {
super.run();
for (int i = 0; i < 1000; i++) {
System.out.println("B 执行中: " + i + ", isDaemon: " + isDaemon());
}
System.out.println("B 执行结束");
}
};
NukixThread A = new NukixThread("A") {
@Override
public void run() {
super.run();
B.start();
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("A 执行结束");
}
};
B.setDaemon(true);
A.start();
线程 ID: 15, 线程名称: A
线程 ID: 14, 线程名称: B
B 执行中: 0, isDaemon: true
B 执行中: 1, isDaemon: true
...
A 执行结束
...
B 执行中: 116, isDaemon: true
可以看出, B 正常情况应该输出 999 但输出到 116 就已经不输出, 而且也没有输出执行结束, 程序已经停止。 因为 B 设置为守护线程, 用户线程(main线程、A线程)已经停止, 所以 守护线程 B 被迫停止了。