Thread类是java中线程的定义,创建时可以设置线程要执行的代码,调用start方法会创建并执行真正的线程,通知管理线程的中断和线程的状态。
目录
4. sleep等待中的线程收到中断标记,会抛出InterruptedException异常,并清除中断标记
1. 创建并执行一个简单的线程
package org.example.concurrent;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.util.concurrent.TimeUnit;
@Slf4j
public class ThreadTest {
@Test
public void test() {
// 创建线程,入参为线程要执行的代码,这里打印一行日志
Thread thread = new Thread(() -> log.debug("Hello world!"));
// 创建并执行线程
thread.start();
sleep(10L);
}
@SneakyThrows
private void sleep(long delay) {
TimeUnit.MILLISECONDS.sleep(delay);
}
}
2.sleep方法主动休眠
Thread的静态方法sleep可以让线程主动休眠,入参为休眠的指定时间
package org.example.concurrent;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.util.concurrent.TimeUnit;
@Slf4j
public class ThreadTest {
@Test
public void test() {
// 创建线程,入参为线程要执行的代码,这里打印一行日志
Thread thread = new Thread(() -> {
log.debug("start");
sleep(1000L); // 休眠1秒
log.debug("end");
});
// 创建并执行线程
thread.start();
sleep(2000L);
}
@SneakyThrows
private void sleep(long delay) {
TimeUnit.MILLISECONDS.sleep(delay);
}
}
log日志end会比start晚1秒打印,打印结果如下:
21:27:30.627 [Thread-0] DEBUG org.example.concurrent.ThreadTest - start
21:27:31.644 [Thread-0] DEBUG org.example.concurrent.ThreadTest - end
3.线程中断
Thread的interrupt方法用于设置线程中断标记。
Thread的isInterrupted方法用于判断线程是否有中断标记
Thread的静态方法interrupted返回当前线程是否有中断标记,并清除中断标记。
示例1: sInterrupted方法用于判断线程是否有中断标记
package org.example.concurrent;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.util.concurrent.TimeUnit;
@Slf4j
public class ThreadTest {
@Test
public void test() {
// 创建线程,入参为线程要执行的代码,这里打印一行日志
Thread thread = new Thread(() -> {
Thread currentThread = Thread.currentThread();
while (!currentThread.isInterrupted()) {
// 线程未中断这一直执行
}
log.debug("当前中断标记为:{}", currentThread.isInterrupted());
}, "t1");
// 创建并执行线程
thread.start();
sleep(10);
// 中断线程
thread.interrupt();
sleep(1000);
}
@SneakyThrows
private void sleep(long delay) {
TimeUnit.MILLISECONDS.sleep(delay);
}
}
执行结果:
21:40:33.816 [t1] DEBUG org.example.concurrent.ThreadTest - 开始sleep
21:40:33.833 [t1] DEBUG org.example.concurrent.ThreadTest - currentThread has been interrupted
示例2:静态方法interrupted返回当前线程是否有中断标记,并清除中断标记
package org.example.concurrent;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.util.concurrent.TimeUnit;
@Slf4j
public class ThreadTest {
@Test
public void test() {
Thread thread = new Thread(() -> {
Thread currentThread = Thread.currentThread();
while (true) {
if (Thread.interrupted()) {
log.debug("检测到当前线程中断");
break;
}
}
log.debug("中断标记:{}", currentThread.isInterrupted());
}, "t1");
// 创建并执行线程
thread.start();
sleep(10);
// 中断线程
thread.interrupt();
sleep(1000L);
}
@SneakyThrows
private void sleep(long delay) {
TimeUnit.MILLISECONDS.sleep(delay);
}
}
执行结果:
21:48:37.217 [t1] DEBUG org.example.concurrent.ThreadTest - 检测到当前线程中断
21:48:37.221 [t1] DEBUG org.example.concurrent.ThreadTest - 中断标记:false
4. sleep等待中的线程收到中断标记,会抛出InterruptedException异常,并清除中断标记
除了sleep,join,wait收到中断标记,都会抛出InterruptedException异常,并清除中断标记。
package org.example.concurrent;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.util.concurrent.TimeUnit;
@Slf4j
public class ThreadTest {
@Test
public void test() {
Thread thread = new Thread(() -> {
log.debug("t1开始睡眠");
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
log.debug("sleep抛出InterruptedException异常,当前线程的中断标记为:{}", Thread.currentThread().isInterrupted());
}
}, "t1");
thread.start();
sleep(10L);
thread.interrupt(); //中断线程
sleep(1000L);
}
@SneakyThrows
private void sleep(long delay) {
TimeUnit.MILLISECONDS.sleep(delay);
}
}
5. 线程同步join
Thread的join方法用于线程同步,即当前线程等待指定线程执行完毕,也可以设置最大等待时间,当前线程等待超过最大等待时间后,会继续往下执行:
package org.example.concurrent;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.util.concurrent.TimeUnit;
@Slf4j
public class ThreadTest {
@Test
public void test() throws InterruptedException {
Thread t1 = new Thread(() -> {
log.debug("t1开始执行");
sleep(1000L);
log.debug("t1执行完毕");
}, "t1");
t1.start();
log.debug("开始执行t1.join");
t1.join();
log.debug("t1.join已经返回");
}
@SneakyThrows
private void sleep(long delay) {
TimeUnit.MILLISECONDS.sleep(delay);
}
}
执行过程中,在线程t1执行完毕后,t1.join才会返回,主线程继续执行,执行结果如下:
22:15:10.527 [t1] DEBUG org.example.concurrent.ThreadTest - t1开始执行
22:15:10.527 [main] DEBUG org.example.concurrent.ThreadTest - 开始执行t1.join
22:15:11.533 [t1] DEBUG org.example.concurrent.ThreadTest - t1执行完毕
22:15:11.534 [main] DEBUG org.example.concurrent.ThreadTest - t1.join已经返回
6 线程两阶段终止线程中断示例
所谓两阶段终止是指:
- 主动调用isInterrupted检查是否被中断,如果被中断则进入中断处理
- 如果使用了sleep、join、wait等操作,需要catch中断异常,并进入中断处理
package org.example.concurrent;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.util.concurrent.TimeUnit;
@Slf4j
public class ThreadTest {
@Test
public void test() throws InterruptedException {
Thread t1 = new Thread(this::monitor, "t1");
t1.start();
sleep(10L);
t1.interrupt();
t1.join();
}
private void monitor() {
Thread currentThread = Thread.currentThread();
// 1.while条件为当前线程未中断,则一直执行
while (!currentThread.isInterrupted()) {
try {
log.debug("monitor 处理");
Thread.sleep(5L);
} catch (InterruptedException e) {
// sleep抛出异常后,会清除中断标记,重新设置中断标记,也可以直接break
currentThread.interrupt();
}
}
log.debug("中断处理");
}
@SneakyThrows
private void sleep(long delay) {
TimeUnit.MILLISECONDS.sleep(delay);
}
}
执行结果:
22:25:43.634 [t1] DEBUG org.example.concurrent.ThreadTest - monitor 处理
22:25:43.644 [t1] DEBUG org.example.concurrent.ThreadTest - monitor 处理
22:25:43.650 [t1] DEBUG org.example.concurrent.ThreadTest - monitor 处理
22:25:43.652 [t1] DEBUG org.example.concurrent.ThreadTest - 中断处理