关于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也不会导致异常

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

线程退出相关

时间: 2024-10-05 10:53:28

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

Java线程:创建与启动

Java线程:创建与启动 一.定义线程 1.扩展java.lang.Thread类. 此类中有个run()方法,应该注意其用法: public void run() 如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法:否则,该方法不执行任何操作并返回.   Thread 的子类应该重写该方法. 2.实现java.lang.Runnable接口. void run() 使用实现接口 Runnable 的对象创建一个线程时,启动该线程将导致在独

java线程详解

Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程.比如在Windows系统中,一个运行的exe就是一个进程. 线程是指进程中的一个执行流程,一个进程中可以运行多个线程.比如java.exe进程中可以运行很多线程.线程总是属于某个进程,进程中的多个线程共享进程的内存. “同时”执行是人的感觉,在线程之间实际上轮换执行. 二.Jav

Java线程详解----借鉴

Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程.比如在Windows系统中,一个运行的exe就是一个进程. 线程是指进程中的一个执行流程,一个进程中可以运行多个线程.比如java.exe进程中可以运行很多线程.线程总是属于某个进程,进程中的多个线程共享进程的内存. “同时”执行是人的感觉,在线程之间实际上轮换执行. 二.Jav

Java线程:概念与原理

一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程.比如在Windows系统中,一个运行的exe就是一个进程. 线程是指进程中的一个执行流程,一个进程中可以运行多个线程.比如java.exe进程中可以运行很多线程.线程总是属于某个进程,进程中的多个线程共享进程的内存. "同时"执行是人的感觉,在线程之间实际上轮换执行. 二.Java中的线程 在J

java线程中断和终止线程运行

ava中启动一个线程很容易,通常情况下我们都是等到任务运行结束后让线程自行停止.但有时需要在任务正在运行时取消他们,使得线程快速结束.对此Java并没有提供任何机制.但是我们可以通过Java提供的线程中断机制来实现. 首先来看Thread类三个和中断有关的方法: public class Thread { // 发出一个中断请求,把标志位设定为中断状态,不会终止线程运行. // 其他线程试图调用该方法,会检测是否有权限中断该线程(正常情况 // 下不会存在权限问题,这里可以忽略) public

Java线程阻塞中断和LockSupport的常见问题

上周五和周末,工作忙里偷闲,在看java cocurrent中也顺便再温故了一下Thread.interrupt和java 5之后的LockSupport的实现. 在介绍之前,先抛几个问题. Thread.interrupt()方法和InterruptedException异常的关系?是由interrupt触发产生了InterruptedException异常? Thread.interrupt()会中断线程什么状态的工作? RUNNING or BLOCKING? 一般Thread编程需要关注

java线程 — 创建和启动线程

创建和启动线程,传统有两种方式: 方式1:继承Thread类: 方式2:实现Runnable接口: 线程类(java.lang.Thread):Thread类和Thread的子类才能称之为线程类.阅读API main方法就是一个主线程 方式1: 步骤: 1. 定义一个类A继承于java.lang.Thread类. 2. 在A类中覆盖Thread类中run方法. 3. 我们在run方法中编写需要执行的操作---->run方法里的,线程执行体 4. 在main方法(线程)中,创建线程对象,并启动线程

java线程中断

java线程中断[interrupt()函数] http://vikings825.iteye.com/blog/964644 停止Java线程,小心interrupt()方法  这篇写的是怎么  正确的 停止 一个线程 http://blog.csdn.net/wxwzy738/article/details/8516253 聊聊并发——生产者消费者模式 http://www.infoq.com/cn/articles/producers-and-consumers-mode/

用interrupt()中断Java线程

最近在学习Java线程相关的东西,和大家分享一下,有错误之处欢迎大家指正. 假如我们有一个任务如下,交给一个Java线程来执行,如何才能保证调用interrupt()来中断它呢? Java代码   class ATask implements Runnable{ private double d = 0.0; public void run() { //死循环执行打印"I am running!" 和做消耗时间的浮点计算 while (true) { System.out.printl