Java 中 Thread 的中断方法
Java juc 面试 About 5,840 wordsinterrupt()
给线程设置一个中断状态,线程仍会继续运行。
但如果线程正好处于等待状态(如:调用wait()
、sleep()
、join()
方法),此时调用interrupt()
方法,则线程立即被唤醒并抛出InterruptedException
异常,然后继续执行sleep()
后的代码。
public static void main(String[] args) throws InterruptedException {
Thread.onSpinWait();
Thread thread = new Thread(() -> {
System.out.println(LocalDateTime.now() + " this is thread beginning..." + Thread.currentThread().getState());
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(LocalDateTime.now() + " this is thread ending..." + Thread.currentThread().getState());
});
thread.start();
TimeUnit.SECONDS.sleep(1);
thread.interrupt();
}
输出
2021-04-11T18:25:15.281534800 this is thread beginning...RUNNABLE
java.lang.InterruptedException: sleep interrupted
at java.base/java.lang.Thread.sleep(Native Method)
at java.base/java.lang.Thread.sleep(Thread.java:339)
at java.base/java.util.concurrent.TimeUnit.sleep(TimeUnit.java:446)
at thread.ThreadInterruptDemo.lambda$main$0(ThreadInterruptDemo.java:16)
at java.base/java.lang.Thread.run(Thread.java:834)
2021-04-11T18:25:16.239082300 this is thread ending...RUNNABLE
isInterrupted()
测试此线程是否被中断,不清除中断状态。
Thread.interrupted()
静态方法。
测试调用此方法的线程是否被中断,清除中断状态标志位并返回true
。第二次调用因为第一次已经清除了中断状态标志位,故返回false
。
public static void main(String[] args) {
Thread.onSpinWait();
Thread thread = new Thread(() -> {
Thread currentThread = Thread.currentThread();
System.out.println(LocalDateTime.now() + " this is thread beginning..." + currentThread.getState());
currentThread.interrupt();
System.out.println("isInterrupted1 = " + currentThread.isInterrupted());
System.out.println("isInterrupted2 = " + currentThread.isInterrupted());
System.out.println("interrupted1 = " + Thread.interrupted());
System.out.println("interrupted2 = " + Thread.interrupted());
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(LocalDateTime.now() + " this is thread ending..." + currentThread.getState());
});
thread.start();
}
输出:
2021-04-11T20:14:44.122852600 this is thread beginning...RUNNABLE
isInterrupted1 = true
isInterrupted2 = true
interrupted1 = true
interrupted2 = false
2021-04-11T20:14:54.176544400 this is thread ending...RUNNABLE
Thread.yield()
调用Thread.yield
后,线程让出CPU
,CPU
调度优先级比当前线程更高或者优先级相等的线程,也有可能继续调度到自己线程,继续执行后续代码。
在并发场景下,可以提高CPU
利用率。
源码分析
public class Thread implements Runnable {
// 该对象包含在一个线程中,该线程被一个可中断的 I/O 操作阻塞
// blocker 对象的中断方法将在被设置该线程的中断状态后调用
private volatile Interruptible blocker;
// 对象锁
private final Object blockerLock = new Object();
// 设置一个中断状态
public void interrupt() {
// 如果不在运行线程中调用
if (this != Thread.currentThread()) {
// 检测是否有权限,通过所属线程组判断,没权限抛出异常
checkAccess();
// 线程可能被 I/O 操作阻塞
synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
interrupt0(); // 设置中断状态标志位
b.interrupt(this); // 调用中断方法
return;
}
}
}
// 如果是在运行线程中调用,直接设置中断状态标志位
interrupt0();
}
// native 方法
// 设置中断状态标志位
private native void interrupt0();
// 测试线程是否中断
// 底层调用 Thread 私有的方法 isInterrupted(boolean)
// false 表示不清除中断状态标志位
public boolean isInterrupted() {
return isInterrupted(false);
}
// 静态方法
// 测试当前线程(Thread.interrupted() 在哪里调用就是测试的哪个线程)是否被中断
// 底层调用 Thread 私有的方法 isInterrupted(boolean)
// true 表示清除中断状态标志位
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
// native 方法
// 测试线程是否被中断,根据 ClearInterrupted 参数决定是否重置中断状态标志位
@HotSpotIntrinsicCandidate
private native boolean isInterrupted(boolean ClearInterrupted);
// 让出 CPU 执行权
public static native void yield();
}
应用场景
FutureTask
源码中在get()
方法中,将等待任务插入链表中。
private int awaitDone(boolean timed, long nanos) throws InterruptedException {
long startTime = 0L; // Special value 0L means not yet parked
WaitNode q = null;
boolean queued = false;
for (;;) {
int s = state;
if (s > COMPLETING) {
if (q != null)
q.thread = null;
return s;
}
else if (s == COMPLETING)
// We may have already promised (via isDone) that we are done
// so never return empty-handed or throw InterruptedException
Thread.yield();
else if (Thread.interrupted()) {
removeWaiter(q);
throw new InterruptedException();
}
else if (q == null) {
if (timed && nanos <= 0L)
return s;
q = new WaitNode();
}
else if (!queued)
queued = WAITERS.weakCompareAndSet(this, q.next = waiters, q);
else if (timed) {
final long parkNanos;
if (startTime == 0L) { // first time
startTime = System.nanoTime();
if (startTime == 0L)
startTime = 1L;
parkNanos = nanos;
} else {
long elapsed = System.nanoTime() - startTime;
if (elapsed >= nanos) {
removeWaiter(q);
return state;
}
parkNanos = nanos - elapsed;
}
// nanoTime may be slow; recheck before parking
if (state < COMPLETING)
LockSupport.parkNanos(this, parkNanos);
}
else
LockSupport.park(this);
}
}
Views: 2,642 · Posted: 2021-04-13
————        END        ————
Give me a Star, Thanks:)
https://github.com/fendoudebb/LiteNote扫描下方二维码关注公众号和小程序↓↓↓
Loading...