java 线程退出问题(interrupt()与中断标志)

 以下下内容均来自网络,只是整理一下;:)

曾经在http://www.iteye.com/topic/1116679,回帖很多,前段时间一直比较忙,没整理。。。;

1) 介绍一下java线程一共有几个状态;

 此图来之core java

  顺便说下,new一个线程出来后,调用start 方法才是处于runnable ,而不是的run()方法线;

  值得注意的是: 线程的可运行状态并不代表线程一定在运行(runnable != running ) 。 大家都知道:所有现代桌面和服务器操作系统都使用了抢占式的线程调度策略 。一旦线程开始执行,并不是总是保持持续运行状态的。当系统分给它的时间片(非常小的运行时间单位)用完以后,不管程序有没有执行完,线程被强制放弃CPU,进入就绪状态,直到下次被调度后开始继续执行。也就是说, Runnable可运行状态的线程处于两种可能的情况下:(1)占用CPU运行中,(2)等待调度的就绪状态。 这里要声明一下:处于等待调度的就绪状态线程和处于阻塞的线程是完全不同的。就绪的线程是因为时间片用完而放弃CPU,其随时都有可能再次获得CPU而运行,这一切取决于分时OS的线程调度策略。(http://hxraid.iteye.com/blog/429005

 2)一下内容参考了http://fujohnwang.github.com/statics/52jump/TerminateJavaThreadGracefully.html

    文中提到比较和谐的结束一个线程 代码如下

1.继承thread类

public class GracefulTerminationSupportThread extends Thread {

    protected volatile boolean running = true;

    @Override
    public void run() {
        while (running) {
            // do something as per specific situations
        }
    }

    public void terminate() {
        running = false;
        interrupt();
    }

    public static void main(String[] args) {
        GracefulTerminationSupportThread t = new GracefulTerminationSupportThread();
        t.start();
        // do other things
        t.terminate();
    }
}
2 实现runnable 写法

public class TerminalSignalSupportRunnable implements Runnable {

    protected volatile boolean running = true;
    
    public void run(){
    	while(running){
    		...
    	}
    }

    public void terminate(Thread threadHandle) {
        running = false;
        threadHandle.interrupt();
    }
}
	
若把terminate 方法里的 threadHandle.interput()换成如下代码,则不会正常终止,为啥会这样,请见作者博文

Thread.currentThread().interrupt();
3)线程中断  —— interrupt();

api 1.6  对中断是这么解释:

Interrupts this thread.

Unless the current thread is interrupting itself, which is always permitted, thecheckAccess method of this thread is invoked, which may cause aSecurityException to be thrown.

If this thread is blocked in an invocation of thewait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive anInterruptedException.

If this thread is blocked in an I/O operation upon aninterruptible channel then the channel will be closed, the thread's interrupt status will be set, and the thread will receive aClosedByInterruptException.

If this thread is blocked in a Selector then the thread's interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selector'swakeup method were invoked.

If none of the previous conditions hold then this thread's interrupt status will be set.

Interrupting a thread that is not alive need not have any effect.

1.当线程不是处于api 提出中的三个if 状态,调用 interrupt() 方法,会改变线程的中断标志。

2.当线程处于三个if状态,调用 interrupt() 方法,只把线程提早的结束阻塞状态(处于阻塞状态的线程,没有获得cpu资源),让线程继续运行,他的中断标志不变,

3. 线程结束运行后的,他的中断标志也是false

4.没有任何语言方面的需求要求一个被中断的程序应该终止。中断一个线程只是为了引起该线程的注意,被中断线程可以决定如何应对中断

接下让我们看下如下程序的运行结果:

public class A extends Thread {


public A(){

}
public void run(){
while(!Thread.currentThread().isInterrupted()){
System.out.println("A  在中断前:"+Thread.currentThread().isInterrupted());
/*try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
System.out.println("--A  在中断异常---:"+isInterrupted());
interrupt();
System.out.println("######A  异常后继续中断---:"+isInterrupted());
e.printStackTrace();
}*/
}

}


}

public class c {


/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub


A aa = new A();
aa.start();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("***********************C 中判断前"+aa.isInterrupted());
aa.interrupt();// 中断
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(" C 中判断 后isInterrupted()*******************;" + aa.isInterrupted());
}


}

去掉A中的注释,然后在运行

---------------------------------------------------------------------------------------------------------------------------------

以下是一个回帖的内容摘要,这兄弟 ,功底深厚

/* 
* 如果线程被阻塞,它便不能核查共享变量,也就不能停止。这在许多情况下会发生,例如调用
* Object.wait()、ServerSocket.accept()和DatagramSocket.receive()时,他们都可能永
* 久的阻塞线程。即使发生超时,在超时期满之前持续等待也是不可行和不适当的,所以,要使
* 用某种机制使得线程更早地退出被阻塞的状态。很不幸运,不存在这样一种机制对所有的情况
* 都适用,但是,根据情况不同却可以使用特定的技术。使用Thread.interrupt()中断线程正
* 如Example1中所描述的,Thread.interrupt()方法不会中断一个正在运行的线程。这一方法
* 实际上完成的是,在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞的状态。更
* 确切的说,如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞,那么,
* 它将接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态。因此,
* 如果线程被上述几种方法阻塞,正确的停止线程方式是设置共享变量,并调用interrupt()(注
* 意变量应该先设置)。如果线程没有被阻塞,这时调用interrupt()将不起作用;否则,线程就
* 将得到异常(该线程必须事先预备好处理此状况),接着逃离阻塞状态。在任何一种情况中,最
* 后线程都将检查共享变量然后再停止。下面示例描述了该技术。
* */
package Concurrency.Interrupt;

class Example3 extends Thread {

volatile boolean stop = false;

public static void main(String args[]) throws Exception {
Example3 thread = new Example3();

System.out.println("Starting thread...");
thread.start();

Thread.sleep(3000);

System.out.println("Asking thread to stop...");

/*
* 如果线程阻塞,将不会检查此变量,调用interrupt之后,线程就可以尽早的终结被阻 
* 塞状 态,能够检查这一变量。
* */
thread.stop = true;

/*
* 这一方法实际上完成的是,在线程受到阻塞时抛出一个中断信号,这样线程就得以退
* 出阻 塞的状态
* */
thread.interrupt();

Thread.sleep(3000);
System.out.println("Stopping application...");
System.exit(0);
}

public void run() {
while (!stop) {
System.out.println("Thread running...");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// 接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态
System.out.println("Thread interrupted...");
}
}

System.out.println("Thread exiting under request...");
}
}
/*
* 把握几个重点: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方法执行完 毕,线程终止。

* */

在上一篇Ibm社区关于

Dealing with InterruptedException;

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值