首页 > 代码库 > 关于java线程的一些特性 启动 中断 及如何退出

关于java线程的一些特性 启动 中断 及如何退出

还是从一道试题说起

public class TestThread {
	public static void main(String[] args){
		// test1
		Thread t1 = new Thread(){
			public void run(){
				try {
					int i = 0;
					while(i++<100000000){
						
					}
					System.out.println("A1");
				} catch (Exception e) {
					System.out.println("B1");
				}
			}
		};
		t1.start();
		t1.interrupt();
		
		// test2
		Thread t2 = new Thread(){
			public void run(){
				try {
					Thread.sleep(5000);
					System.out.println("A2");
				} catch (Exception e) {
					System.out.println("B2");
				}
			}
		};
		t2.start();
		t2.interrupt();
		
		// test3
		Thread t3 = new Thread(){
			public void run(){
				try {
					this.wait(50000);
					System.out.println("A3");
				} catch (Exception e) {
					System.out.println("B3");
				}
			}
		};
		t3.start();
		t3.interrupt();
		
		// test1
		Thread t4 = new Thread(){
			public void run(){
				try {
					synchronized (this) {
						this.wait(50000);
					}
					System.out.println("A4");
				} catch (Exception e) {
					System.out.println("B4");
				}
			}
		};
		t4.start();
		t4.interrupt();
		
		// test5
		try {
			t4.start();
			System.out.println("A5");
		} catch (Exception e) {
			System.out.println("B5");
		}
	}
}
实际运行后,我们发现结果是

B3
B5
B4
B2
A1
为什么会这样呢?其实api文档中就有详细的描述如下:

如果线程在调用 Object 类的wait()wait(long)wait(long, int) 方法,或者该类的 join()join(long)join(long, int)sleep(long)sleep(long, int) 方法过程中受阻,则其中断状态将被清除,它还将收到一个InterruptedException

所以在interrupt执行后,对应的线程会放弃睡眠操作,同时抛出异常。所以这里会输出B2,B3  


关于B4,在线程进入this.wait段代码之后,由于wait的特性,会将对象锁释放出来。之后直到interrupt执行之后,会先获取对象锁,之后放弃wait并抛出异常

关于B5,同一thread对象的start方法只能够被调用一次,当已经启动状态下调用start会抛出IllegalThreadStateException ,如果已经结束,有可能对象都被回收了,所以start更不可能

关于A1,涉及到在interrupt执行后到底改变了什么。实际上在线程interrupt后,只是改变了线程的中断状态而已,如果线程不对该状态进行检测,则线程会一直继续执行下去。直到内部任务完成。我们在print A1时同时打印i,会发现,i此时值已经为100000001已经达到退出条件。那么如何让interrupt的线程能够退出呢,方法如下

		Thread t1 = new Thread(){
			public void run(){
				try {
					int i = 0;
					while(!Thread.currentThread().isInterrupted()){
						while(i++<100000000){
							
						}
					}
					
					System.out.println("A1 "+i);
				} catch (Exception e) {
					System.out.println("B1");
				}
			}
		};
		t1.start();
		t1.interrupt();
结论:

当线程当前在运行状态,如果没有判断isInterrupted标志,实际上什么也不会发生

而当线程在阻塞状态时(sleep wait join),执行interrupt会因为抛出异常而提前退出阻塞状态

当存在同步锁的情况下,wait会将同步锁释放出来,如果拿不到同步锁,interrupt也不会导致异常

如果想进一步了解的可以参考

线程退出相关

关于java线程的一些特性 启动 中断 及如何退出