简单理解线程--阻塞,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的主要内容,如果未能解决你的问题,请参考以下文章
java中的interrupt(),InterruptException和wait(),sleep()