|
线程中断 |
|
|
线程中断机制
1、线程中断和线程终止的区别
2、判断线程是否被中断
3、线程中断在线程中的使用方法
1、线程中断和线程终止的区别
线程终止:当线程run()方法执行方法体中的最后一条语句后,并经执行return语句返回时,或出现方法没有捕获异常时线程终止。
线程中断:因为任何一个线程都不该被其他线程终止,所以我们引入Thread.interrupt()方法,来通知线程运行到某个地方该中断了,至于中断的结果线程是死亡、还是等待新的任务或是继续运行至下一步,由这个程序自身决定。
2、判断线程是否被中断
每个线程都具有boolean标志,用来判断是否到该被中断的位置了。中断线程的方法是:Thread.interrupt()方法。它将会设置该线程的中断状态标示位,并设置为true。线程会不时地检测这个中断标示位(判断某个线程是否已被发送过中断请求,使用
Thread.currentThread().isInterrupted()方法),来判断是否该提醒线程可以被中断了(即中断标示值是否为true)。
isInterrupted()方法和interrupt()方法区别:前者不会改变线程是否中断的属性值,后者可以将值设置为false,interrupt是一个静态方法,平时开发推荐使用isInterrupt()方法。
注意:synchronized在获锁的过程中是不能被中断的,意思是说如果产生了死锁,则不可能被中断
与synchronized功能相似的reentrantLock.lock()方法也是一样,它也不可中断的,即如果发生死锁,那么reentrantLock.lock()方法无法终止,如果调用时被阻塞,则它一直阻塞到它获取到锁为止。
3、线程中断在线程中的使用方法
Thread.interrupt()方法的作用是在线程受到阻塞时抛出一个中断信号,使线程退出阻塞状态。即:如果线程被Object.wait,Thread.join和Thread.sleep三种方法之一阻塞,那么,它将接收到一个中断异常(interruptedException),从而提早地终结被阻塞状态。
备注:Thread.sleep方法也可以产生InterruptedException,因此如果每次在做完工作后调用了sleep方法,可以不用检查isInterrupted,而是直接捕捉InterruptedException。
在中断发生后,线程仍然在运行时:
抛出InterruptException和用Thread.interrupted()唤醒阻塞,检查是否发生中断:
在阻塞操作时如:Thread.Sleep()时被中断,会抛出InterruptedException
代码如下:
publicclassInterruptTaskTest{
publicstaticvoidmain(String[]args)throwsException{
//将任务交给一个线程
//ATaska=newATask();
ATask1a1=newATask1();
//ATask2a2=newATask2();
//ATask3a3=newATask3();
Threadt=newThread(a1);
System.out.println("线程启动");
t.start();
//运行一段时间中断线程
//Thread.sleep(5000);
System.out.println("--线程停止--");
Thread.sleep(3000);
t.interrupt();//唤醒阻塞
System.out.println("t-inter");
}
}
classATask1implementsRunnable{
privatedoubled=0.0;
publicvoidrun(){
//死循环执行打印“等中断” try{
while(true){
System.out.println("本线程还活着");
for(inti=0;i<100;i++){
System.out.println("等中断"+i);
}
//中断一段时间后抛出InterruptedException
Thread.sleep(100);
}
}catch(InterruptedExceptione){
System.out.println("———本线程已中断———");
}
}
}
2)Thread.interrupted()检查是否发生中断。Thread.interrupted()能告诉我们线程是否发生中断,并将清除中断状态标记,唤醒阻塞,所以程序不会两次通知线程发生中断。
代码如下:
classATask2implementsRunnable{
publicvoidrun(){
//检查程序是否发生中断
while(!Thread.interrupted()){
System.out.println("等着看循环");
//Thread.sleep(5000);
for(inti=0;i<100;i++){
System.out.println("我还在运行"+i);
try{
Thread.sleep(1000);
System.out.println(System.currentTimeMillis());
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
}
}
中断线程没发生:
如果当前线程没有中断它自己(这在任何情况下都是允许的),则该线程的checkAccess方法就会被调用,这可能抛出SecurityException。如果线程在调用Object类的wait()、wait(long)或wait(long,int)方法,或者该类的join()、join(long)、join(long,int)、sleep(long)或sleep(long,int)方法过程中受阻,则其中断状态将被清除,它还将收到一个InterruptedException。
如果该线程在可中断的通道上的I/O操作中受阻,则该通道将被关闭,该线程的中断状态将被设置并且该线程将收到一个ClosedByInterruptException。
如果该线程在一个Selector中受阻,则该线程的中断状态将被设置,它将立即从选择操作返回,并可能带有一个非零值,就好像调用了选择器的wakeup方法一样。
如果以前的条件都没有保存,则该线程的中断状态将被设置。
中断一个不处于活动状态的线程不需要任何作用。
|
|
|
|
|
|
|
|
|
|
|