简单理解线程--阻塞,interrupt

Posted black_Style

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了简单理解线程--阻塞,interrupt相关的知识,希望对你有一定的参考价值。

什么是线程

  线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程自己基本不拥有资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进行所拥有的所有资源。

阻塞和非阻塞

  阻塞和非阻塞是形容多个线程之间的相互影响的(前提是多线程而不是一个),一个线程占用了临界区资源,那么其他线程必须在临界区外等待,阻塞是操作系统层面挂起,上下文切换了,所以性能不高。如果一个线程一直占用不释放资源,那么其他需要该临界区资源的线程都必须一直等待。非阻塞就是运行多个线程同时进入临界区,只要保证不把数据修改坏就行。

阻塞的情况分三种:

  • 等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
  • 同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
  • 其他阻塞:运行的线程执行sleep()或join()方法时,或者发出I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时,join()等待线程终止或者超时,或者I/O处理完毕时,线程重新转入就绪状态。
 1 /*   
 2 
 3  * 如果线程被阻塞,它便不能核查共享变量,也就不能停止。这在许多情况下会发生,例如调用  
 4  * Object.wait()、ServerSocket.accept()和DatagramSocket.receive()时,他们都可能永  
 5  * 久的阻塞线程。即使发生超时,在超时期满之前持续等待也是不可行和不适当的,所以,要使  
 6  * 用某种机制使得线程更早地退出被阻塞的状态。很不幸运,不存在这样一种机制对所有的情况  
 7  * 都适用,但是,根据情况不同却可以使用特定的技术。使用Thread.interrupt()中断线程  
 8  * Thread.interrupt()方法不会中断一个正在运行的线程。这一方法  
 9  * 实际上完成的是,在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞的状态。更  
10  * 确切的说,如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞,那么,  
11  * 它将接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态。因此,  
12  * 如果线程被上述几种方法阻塞,正确的停止线程方式是设置共享变量,并调用interrupt()(注  
13  * 意变量应该先设置)。如果线程没有被阻塞,这时调用interrupt()将不起作用;否则,线程就  
14  * 将得到异常(该线程必须事先预备好处理此状况),接着逃离阻塞状态。在任何一种情况中,最  
15  * 后线程都将检查共享变量然后再停止。下面示例描述了该技术。  
16  * */
17 class Example extends Thread {
18 
19     volatile boolean stop = false;
20 
21     public static void main(String args[]) throws Exception {
22         Example thread = new Example();
23 
24         System.out.println("Starting thread...");
25         thread.start();
26         
27         System.out.println("sleep 3S......");
28         Thread.sleep(3000);
29 
30         System.out.println("Asking thread to stop...");
31 
32         /*
33          * 如果线程阻塞,将不会检查此变量,调用interrupt之后,线程就可以尽早的终结被阻塞状态,能够检查这一变量。
34          */
35         System.out.println("stop==true......");
36         thread.stop = true;
37         
38         
39         /*
40          * 这一方法实际上完成的是,在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞的状态
41          */
42         System.out.println("interrupt......");
43         thread.interrupt();
44         
45         Thread.sleep(3000);
46         System.out.println("Stopping application...");
47         System.exit(0);
48     }
49 
50     public void run() {
51         while (!stop) {
52             System.out.println("Thread running...");
53             try {
54                 System.out.println("sleep  2S......");
55                 Thread.sleep(2000);
56             } catch (InterruptedException e) {
57                 // 接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态
58                 System.out.println("Thread interrupted...");
59             }
60         }
61 
62         System.out.println("Thread exiting under request...");
63     }
64 }

 

把握几个重点:
stop变量、run方法中的sleep()、interrupt()、InterruptedException。串接起来就是这个意思:
  当我们在run方法中调用sleep(或其他阻塞线程的方法)时,如果线程阻塞的时间过长,比如10s,那在这10s内,线程阻塞,run方法不被执行,但是如果在这10s内,stop被设置成true,表明要终止这个线程,但是,现在线程是阻塞的,它的run方法不能执行,自然也就不能检查stop,所以线程不能终止,这个时候,我们就可以用interrupt()方法了:我们在thread.stop = true;语句后调用thread.interrupt()方法, 该方法将在线程阻塞时抛出一个中断信号,该信号将被catch语句捕获到,一旦捕获到这个信号,线程就提前终结自己的阻塞状态,这样,它就能够再次运行run方法了,然后检查到stop = true,while循环就不会再被执行,在执行了while后面的清理工作之后,run方法执行完 毕,线程终止。

http://mp.weixin.qq.com/s/1u95m2EcHFbbJNRv3GJlbQ

以上是关于简单理解线程--阻塞,interrupt的主要内容,如果未能解决你的问题,请参考以下文章

详解线程interrupt()方法

四interrupt()

java中的interrupt(),InterruptException和wait(),sleep()

多线程-interrupt(),isInterrupted(),interrupted()(转)

yield函数 ,interrupt函数

多线程总结持续更新