博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java 线程退出问题(interrupt()与中断标志)
阅读量:2403 次
发布时间:2019-05-10

本文共 5834 字,大约阅读时间需要 19 分钟。

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

曾经在,回帖很多,前段时间一直比较忙,没整理。。。;

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

 此图来之core java

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

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

 2)一下内容参考了

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

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, the method of this thread is invoked, which may cause a to be thrown.

If this thread is blocked in an invocation of the, , or methods of the class, or of the , , , , or , methods of this class, then its interrupt status will be cleared and it will receive an.

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

If this thread is blocked in a 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's 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;

转载地址:http://uppob.baihongyu.com/

你可能感兴趣的文章
存储知识小结
查看>>
温习tcp知识
查看>>
mysql用于分配内存的参数
查看>>
[转载]移动开发谁领风骚 J2ME开发工具面面观
查看>>
[转载]Java嵌入式开发之四-J2ME与MIDP开发
查看>>
java实现屏幕取色
查看>>
[转载]项目经验二则:读取war包中的文件及Ant使用中的OutOfMemoryError解决
查看>>
[转载]实例讲解配置之——TOMCAT集群配置
查看>>
[转载]彻底转变流,第 2 部分:优化 Java 内部 I/O
查看>>
[转载]SWT 和 JFace, 第 2 部分: 简介
查看>>
[转载]ZX手机平台的几个问题
查看>>
[转载]JDBC编程基础
查看>>
[转载]Java手机游戏编程之MIDP图形设计篇
查看>>
[转载]Java Servlets编程指南(十八)
查看>>
DNS配置全文(转)
查看>>
程序界的高手传奇(转)
查看>>
CVS-RCS(2)(转)
查看>>
CVS-RCS(3)(转)
查看>>
CVS-RCS(5)(转)
查看>>
安装Linux的五种方法和心得(转)
查看>>