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