• Java 如何中断和恢复线程的执行


    一、线程的状态

    线程可以阻塞于四种状态:

    1、当线程执行Thread.sleep()时,它一直阻塞到指定的毫秒时间之后,或者阻塞被另一个线程打断;

    2、当线程碰到一条wait()语句时,它会一直阻塞到接到通知notify()、被中断、经过了指定时间为止(若有超时值的话)

    3、线程阻塞与不同I/O的方式

        3.1. 常见的一种方式是InputStream的read()方法,该方法一直阻塞到从流中读取一个字节的数据为止,它可以无限阻塞,因此不能指定超时时间;

      3.2 java.nio 中的非阻塞 I/O 类也不支持可中断 I/O,但是同样可以通过关闭通道或者请求 Selector 上的唤醒来取消阻塞操作

    4、线程也可以阻塞等待获取某个对象锁的排他性访问权限(即等待获得synchronized语句必须的锁时阻塞)。

    注意,并非所有的阻塞状态都是可中断的,以上阻塞状态的前两种可以被中断,后两种不会对中断做出反应

    wait vs blocked


    假设t1,t2先后两个线程,都执行如下代码:
    synchronized(Obj) {
        Obj.wait(); 
    }
    

    t1先进,最后在Obj.wait()下卡住,这时java管t1的状态waitting状态

    t2后进,直接在第一行就卡住了,这时java叫t2为blocked状态。

    请注意,blocked是过去分词,意味着他是被卡住的。因为这段代码只让一条线程运行。同时,jvm是知道怎么结束blocked的,只要别的线程退出这段代码,他就会自动让你进去。也就是说别的线程无需唤醒你,由jvm自动来干

    而waiiting是说我调用wait()等函数,主动卡住自己(我在等一个白富美),请jvm在满足某种条件后(白富美发消息让我们晚上见),比如另条线程调用了notify()后,把我唤醒。这个唤醒的责任在于别的线程(白富美)明确的调用一些唤醒函数。

    做这样的区分,是jvm出于管理的需要,做了这种区分,比如两个原因的线程放两个队列里管理,如果别的线程运行出了synchronized这段代码,我只需要去blocked队列,放个出来。而某人调用了notify(),我只需要去waitting队列里取个出来。

    P.S. 从linux内核来看,这些线程都是等待状态,没区别,区别只在于java的管理需要。通常我们在系统级别说线程的blocked,是说线程操作io,被暂停了,这种线程由linux内核来唤醒(io设备报告数据来了,内核把block的线程放进可运行的进程队列,
     
    依次得到处理器时间),而wait是说,等待一个内核mutex对象,另个线程signal这个mutex后,这个线程才可以运行。区别在于由谁唤醒,是操作系统,还是另一个线程,这里倒和java很相似。

    二、中断某个线程

    当对一个线程,调用 interrupt() 时

    ① 如果线程处于正常活动状态,那么会将该线程的中断标志设置为 true。被设置中断标志的线程将继续正常运行,不受影响。

    ② 如果线程处于被阻塞状态(sleep, wait, join 等状态),那么线程将立即退出被阻塞状态,并抛出一个InterruptedException

    interrupt() 并不能真正的中断线程,需要被调用的线程自己进行配合才行

    ① 在正常运行任务时,经常检查本线程的中断标志位,如果被设置了中断标志就自行停止线程

    ② 在调用阻塞方法时正确处理InterruptedException异常

    1。当线程没有处于阻塞状态,通过改变标志量,可以让线程停止。

     1 public class Example01 extends Thread {
     2     boolean  stop=false;
     3     public static void main( String args[] ) throws Exception {
     4         Example01 thread = new Example01();
     5         thread.start();
     6         Thread.sleep(1000);
     7         thread.interrupt(); //线程不会停止
     8 //      thread.stop = true;  //线程会停止
     9     }
    10     public void run() {
    11         while(!stop){
    12             System.out.println( "Thread is running..." );
    13             
    14         }
    15         System.out.println("Thread exiting..." );
    16         }
    17 }

    2。当线程处于阻塞状态,调用interrupt()方法。

      If this thread is blocked in an invocation of the wait() methods of the Object class, or of the join(), , sleep(long)methods of

    Thread class, then its interrupt status will be cleared and it will receive an InterruptedException.

     1 public class Example01 extends Thread {
     2     boolean  stop=false;
     3     public static void main( String args[] ) throws Exception {
     4         Example01 thread = new Example01();
     5         thread.start();
     6         Thread.sleep(1000);
     7         thread.interrupt(); 
     8         
     9     }
    10     public void run() {                
    11         System.out.println("-------sleeping");
    12         try {
    13             Thread.sleep(2000);
    14         } catch (InterruptedException e) {
    15             e.printStackTrace();
    16         }
    17         System.out.println("-------caclulating");
    18         double d = 0; 
    19         for(int i=1; i<2500000; i++){
    20             d += Math.E/d;
    21         }
    22         System.out.println("-------finish caclulating");        
    23     
    24     }
    25 }

    3.当线程处于阻塞状态,可以中断等待的资源,如I/O, Socket

    参考:

    IBM: 处理InterruptedException

    self: AQS 与 LockSupport

  • 相关阅读:
    IllegalStateException
    TimeUnit简析
    Cron表达式
    任务调度之Timer与TimerTask配合
    Executor简析
    this逃逸
    SQL、SQL Server、MySQL与Oracle
    数据库与实例
    vw 、vh、vmin 、vmax
    逻辑(内存)分页与物理分页
  • 原文地址:https://www.cnblogs.com/yuyutianxia/p/3465206.html
Copyright © 2020-2023  润新知