共计 2592 个字符,预计需要花费 7 分钟才能阅读完成。
Java 进行线程的逻辑(协同、告诉)
在 Java 程序中,咱们想要进行一个线程能够通过 interrupt 办法进行进行。然而当咱们调用 interrupt 办法之后,它可能并不会立即就会进行线程,而是告诉线程须要进行。线程接管到告诉之后会依据本身的状况判断是否须要进行,它可能会立刻进行,也有可能会执行一段时间后进行,也可能基本就不进行。
那么 Java 为什么要抉择这种非强制性的线程中断呢?其实更多是为了数据安全,保障程序的健壮性。因为咱们不晓得程序正在做什么事件。如果贸然进行,可能会造成数据的错乱、不残缺。
一个简略的例子 :
public class _24_ThreadTest implements Runnable {
@Override
public void run() {
int count = 0;
while (!Thread.currentThread().isInterrupted() && count <= 2000) {System.out.println("count:" + count++);
}
}
public static void main(String[] args) throws Exception {_24_ThreadTest threadTest = new _24_ThreadTest();
Thread thread = new Thread(threadTest);
thread.start();
Thread.sleep(10);
// 中断线程
thread.interrupt();}
}
这个例子是一个简略的通过 interrupt 中断线程的案例,run 办法中通过判断以后线程是否中断,并且 count 是否大于 2000 来进行循环。如果线程中断则退出循环,线程执行完结。这种就属于线程失常进行的状况。
Sleep 是否会收到线程中断信号
public class _24_ThreadTest implements Runnable {
@Override
public void run() {
int count = 0;
while (!Thread.currentThread().isInterrupted() && count <= 2000) {
try {System.out.println("count:" + count++);
// 子线程睡眠
Thread.sleep(1000 * 2);
System.out.println("办法体:" + Thread.currentThread().isInterrupted());
} catch (InterruptedException e) {System.out.println("异样:" + Thread.currentThread().isInterrupted());
// 线程中断标记位被重置为 false
e.printStackTrace();}
}
}
public static void main(String[] args) throws Exception {_24_ThreadTest threadTest = new _24_ThreadTest();
Thread thread = new Thread(threadTest);
thread.start();
Thread.sleep(10);
// 中断线程
thread.interrupt();}
}
如果在子线程中睡眠中,主线程通过 interrupt 办法进行中断,那么子线程还能不能收到中断信号。其实在这种状况下线程也是能够接管到信号告诉的,这个时候会抛出 InterruptedException,并且将线程中断标记位设置为 false。
在抛出异样后,线程标记位被设置为 false,那么在下次循环判断 count 没有为 false 的状况下,还是能够进入循环体的。这个时候线程就无奈进行。
执行后果:
案例场景 :
在进行一些后台任务通过线程跑的时候,如果在循环中遇到线程中断异样,咱们须要终止当前任务,并且通知客户端当前任务执行失败的是哪条记录,这种状况下就能够通过异样中再次中断的形式来进行线程,并且能够返回给客户端以后出现异常的记录是哪条。而不会是接着执行上来。
解决办法
public class _24_ThreadTest implements Runnable {
@Override
public void run() {
int count = 0;
while (!Thread.currentThread().isInterrupted() && count <= 2000) {
try {System.out.println("count:" + count++);
// 子线程睡眠
Thread.sleep(1000 * 2);
Thread.currentThread().interrupt();
System.out.println("办法体:" + Thread.currentThread().isInterrupted());
} catch (InterruptedException e) {
// 再次中断
Thread.currentThread().interrupt();
System.out.println("异样:" + Thread.currentThread().isInterrupted());
e.printStackTrace();}
}
}
public static void main(String[] args) throws Exception {_24_ThreadTest threadTest = new _24_ThreadTest();
Thread thread = new Thread(threadTest);
thread.start();
Thread.sleep(10);
// 中断线程
thread.interrupt();}
}
既然咱们曾经晓得,在呈现线程中断异样之后线程中断标记位会被重置为 false,那么咱们能够在异样中手动的再次中断以后线程,那么就能够齐全进行线程工作。
总结
下面咱们简略介绍了如何正确的进行线程,如果在当前的面试中被问到这类问题,那么你是不是能够晦涩的答复面试官了。
在 run 办法中遇到异样,咱们是不能间接生吞的,肯定要做解决,你能够是简略的日志记录,也能够中断线程。但就是不能不做任何解决。
其实还有其余的一些办法来进行线程,比方 stop(),这类办法已被舍弃,这种强制进行可能会引起线程的数据安全问题,所以曾经不再举荐应用了。