自学内容网 自学内容网

003 线程的暂停和中断

暂停

Java中线程的暂停是调用 java.lang.Thread 类的 sleep 方法。该方法会使当前正在执行的线程暂停指定的一段时间,如果线程持有锁, sleep 方法结束前并不会释放该锁。

中断

java.lang.Thread类有一个 interrupt 方法,该方法直接对线程调用。当被interrupt的线程正在sleep或wait时,会抛出 InterruptedException 异常。
事实上, interrupt 方法只是改变目标线程的中断状态(interrupt status),而那些会抛出InterruptedException 异常的方法,如wait、sleep、join等,都是在方法内部不断地检查中断状态的值。

  • interrupt方法

Thread实例方法:必须由其它线程获取被调用线程的实例后,进行调用。实际上,只是改变了被调用线程的内部中断状态;
源码

    public void interrupt() {
        if (this != Thread.currentThread())
            checkAccess();

        synchronized (blockerLock) {
            Interruptible b = blocker;
            if (b != null) {
                interrupt0();           // Just to set the interrupt flag
                b.interrupt(this);
                return;
            }
        }
        interrupt0();
    }
  • Thread.interrupted方法
    Thread类方法:必须在当前执行线程内调用,该方法返回当前线程的内部中断状态,然后清除中断状态(置为false) ;
  • isInterrupted方法
    Thread实例方法:用来检查指定线程的中断状态。当线程为中断状态时,会返回true;否则返回false。

public class ThreadTest {
    public static void main(String[] args) throws InterruptedException {
        StopThread thread = new StopThread();
        thread.start();
        Thread.sleep(1000L);
        thread.interrupt();
        while (thread.isAlive()) { }
        thread.print();
    }
    private static class StopThread extends Thread {
        private int x = 0; private int y = 0;
        @Override
        public void run() {
            synchronized (this) {
                ++x;
                try {
                    Thread.sleep(3000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                ++y;
            }
        }
        public void print() {
            System.out.println("x=" + x + " y=" + y);
        }
    }
}    
        

底层源码实现


// 核心 interrupt 方法
public void interrupt() {
        if (this != Thread.currentThread()) // 非本线程,需要检查权限
        checkAccess();
synchronized (blockerLock) {
        Interruptible b = blocker;
        if (b != null) {
        interrupt0(); // 仅仅设置interrupt标志位
        b.interrupt(this); // 调用如 I/O 操作定义的中断方法
        return;
        }
        }
        interrupt0();
}
// 静态方法,这个方法有点坑,调用该方法调用后会清除中断状态。
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
// 这个方法不会清除中断状态
public boolean isInterrupted() {
return isInterrupted(false);
}
// 上面两个方法会调用这个本地方法,参数代表是否清除中断状态
private native boolean isInterrupted(boolean ClearInterrupted);

interrupt() :

  • interrupt 中断操作时,非自身打断需要先检测是否有中断权限,这由jvm的安全机制配置;
  • 如果线程处于sleep, wait, join 等状态,那么线程将立即退出被阻塞状态,并抛出一个InterruptedException异常;
  • 如果线程处于I/O阻塞状态,将会抛出ClosedByInterruptException(IOException的子类)异常;
  • 如果线程在Selector上被阻塞,select方法将立即返回;
  • 如果非以上情况,将直接标记 interrupt 状态;
    注意:interrupt 操作不会打断所有阻塞,只有上述阻塞情况才在jvm的打断范围内,如处于锁阻塞的线程,不会受 interrupt 中断;

阻塞情况下中断,抛出异常后线程恢复非中断状态,即 interrupted = false

public class ThreadTest {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new Task("mytask"));
        t.start();
        t.interrupt();
    }
    static class Task implements Runnable{
        String name;
        public Task(String name) {
            this.name = name;
        }
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("thread has been interrupt!");
            }
            System.out.println("isInterrupted: " +
                    Thread.currentThread().isInterrupted());
            System.out.println("task " + name + " is over");
        }
    }
}

调用Thread.interrupted() 方法后线程恢复非中断状态


public class ThreadTest {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new Task("mytask"));
        t.start();
        t.interrupt();
    }
    static class Task implements Runnable{
        String name;
        public Task(String name) {
            this.name = name;
        }
        @Override
        public void run() {
            System.out.println("first :" + Thread.interrupted());
            System.out.println("second:" + Thread.interrupted());
            System.out.println("task " + name + " is over");
        }
    }
}


原文地址:https://blog.csdn.net/m0_46695127/article/details/140186572

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!