【Java】【多线程】线程的方法yield
学而不思则罔,思而不学则殆
初步了解
interrupt简单熟悉。
private static void testInterrupt() throws InterruptedException {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("Sleep ... ");
TimeUnit.MINUTES.sleep(1);
} catch (InterruptedException e) {
//e.printStackTrace();
System.out.println("Oh, I am be interrupted.");
}
}
});
thread.start();
TimeUnit.SECONDS.sleep(2);
thread.interrupt();
}
创建一个线程,休眠1分钟,但是在另一个线程执行了interrupt打断了该线程的休眠,线程不会休眠1分钟,会在2秒后被中断。
Sleep ...
Oh, I am be interrupted.
interrupt这个方法到底做了什么呢?在一个线程内部存着一个命名为interrupt flag的标识,如果一个线程被interrupt,那么他的flag将被设置。
中断相关的方法有三个:
方法 | 属性 | 说明 | 是否修改标识 |
---|---|---|---|
interrupt | 类方法 | 设置中断标识 | 修改标识(设置标识) |
isInterrupted | 类方法 | 判断线程是否中断 | 不修改标识 |
interrupted | 静态方法 | 判断线程是否中断 | 修改标识(擦除标识) |
isInterrupted
isInterrupted是Thread的一个成员方法,它主要判断当前线程是否被中断,而且该方法仅是对interrupt标识的一个判断,并不会影响标识发生任何改变。
isInterrupted 测试一
线程中是空实现,调用interrupt打断线程,然后打印中断标识
private static void testInterrupt() throws InterruptedException {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
while (true){
//空实现
}
}
});
thread.setDaemon(true);//设置守护线程,没有非守护线程会退出
thread.start();
TimeUnit.SECONDS.sleep(1);
System.out.println("thread 1 = " + thread.isInterrupted());
thread.interrupt();//打断
System.out.println("thread 2 = " + thread.isInterrupted());
TimeUnit.SECONDS.sleep(1);
System.out.println("thread 3 = " + thread.isInterrupted());
}
测试一结果
thread 1 = false
thread 2 = true
thread 3 = true
最开始标识是false,在执行interrupt后,标识是true。说明线程被打断,只是没有处理。
isInterrupted 测试二
线程中是有sleep,可捕获到中断方法,调用interrupt打断线程,然后打印中断标识
private static void testInterrupt() throws InterruptedException {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("Sleep ... ");
TimeUnit.MINUTES.sleep(1);
} catch (InterruptedException e) {
//e.printStackTrace();
System.out.println("Oh, I am be interrupted.");
}
}
});
thread.setDaemon(true);
thread.start();
TimeUnit.SECONDS.sleep(1);
System.out.println("thread 1 = " + thread.isInterrupted());
thread.interrupt();
System.out.println("thread 2 = " + thread.isInterrupted());
TimeUnit.SECONDS.sleep(1);
System.out.println("thread 3 = " + thread.isInterrupted());
}
测试二结果
Sleep ...
thread 1 = false
Oh, I am be interrupted.
thread 2 = false
thread 3 = false
执行中断interrupt。为啥拿到的中断标识还是false?因为sleep方法是一个可中断方法,会捕获中断标识并擦出,所以获取的中断标识是false。
对比两个测试的结果,可以得出一些结论:
- isInterrupted可以获取当前线程的中断标识,不会改变标识
- sleep方法会捕获中断标识,捕获到后会把标识改为false
interrupted
interrupted是一个静态方法,虽然其也用于判断当前线程是否被中断,但是它和成员方法isInterrupted不同,调用该方法会直接擦除interrupt标识。
interrupted测试
测试当线程的是否被中断。
private static void testInterrupted() throws InterruptedException {
Thread.currentThread().interrupt();
System.out.println(Thread.currentThread().isInterrupted());
System.out.println(Thread.interrupted());
System.out.println(Thread.interrupted());
}
测试一结果
true
true
false
调用interrupt后,设置标识为true。第一次调用interrupted返回的true,并擦除,所以第二次调用interrupted返回的false。isInterrupted不会改变标识,所以为true。
源码解析
//Tests if some Thread has been interrupted. The interrupted state is reset or not based on the value of ClearInterrupted that is passed.
private native boolean isInterrupted(boolean ClearInterrupted);
true 清除标识 false 不清除
public boolean isInterrupted() {
return isInterrupted(false);
}
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
- isInterrupted和interrupted调用的都是同一个native方法,
- isInterrupted方法中的ClearInterrupted = false,表示不想擦除
- interrupted方法中的ClearInterrupted = true,表示想擦除
那么当一个线程没有执行可中断方法之前就被打断,那么接下来该如何执行呢?
private static void testInterrupt1() {
Thread thread = Thread.currentThread();
//1.判断当前线程是否中断
System.out.println("currentThread is interrupt 0 ? " + Thread.interrupted() + " time:" + System.currentTimeMillis());
thread.interrupt(); //2.执行打断方法
System.out.println("currentThread is interrupt 1 ? " + thread.isInterrupted() + " time:" + System.currentTimeMillis());
try {
//3.执行可中断方法sleep
TimeUnit.MINUTES.sleep(1);//会擦出interrupt标识
} catch (InterruptedException e) {
//e.printStackTrace();
//4.捕获中断信号
System.out.println("Oh, I am be interrupted.");
}
//5.打印中断标识
System.out.println("currentThread is interrupt 2 ? " + thread.isInterrupted() + " time:" + System.currentTimeMillis());
}
结果:
currentThread is interrupt 0 ? false time:1599277740140
currentThread is interrupt 1 ? true time:1599277740140
Oh, I am be interrupted.
currentThread is interrupt 2 ? false time:1599277740141
可见sleep立马就结束,立马被打断,标识为false。
总结
interrupt只是添加打断标识,真正打断逻辑还需要我们自己来实现。