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(),这类办法已被舍弃,这种强制进行可能会引起线程的数据安全问题,所以曾经不再举荐应用了。