java线程崩溃,只会终止该线程,不会影响其他线程,主线程崩溃也不影响子线程的执行。
在安卓中,无论主线程还是子线程崩溃,都会导致应用程序退出。
Thread userThread = new Thread(() -> {
System.out.println("用户线程启动");
try {
for (int i = 0; i < 5; i++) {
System.out.println("用户线程运行: " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.out.println("用户线程被中断");
}
System.out.println("用户线程结束");
});
userThread.start();
这段代码创建并启动了一个新的线程(称为userThread),该线程执行以下操作:
- 启动信息打印:首先打印出一条消息 “用户线程启动” 到控制台,表明用户线程已经开始执行。
- 循环执行与休眠:然后,它进入一个循环,循环变量i从0开始,小于5时循环继续。在每次循环中,它首先打印出当前循环的计数 "用户线程运行: " + i,然后调用Thread.sleep(1000);使当前线程(即userThread)暂停执行1秒钟。这样做是为了模拟线程在执行过程中可能会进行的耗时操作或等待。
- 异常处理:如果在Thread.sleep(1000);调用过程中,userThread被其他线程中断(比如通过调用其interrupt()方法),则会抛出InterruptedException。该异常被捕获,并在捕获块中执行两个操作:
首先,通过调用Thread.currentThread().interrupt();重新设置当前线程的中断状态。这是因为在捕获InterruptedException后,JVM会清除线程的中断状态,如果后续代码还需要检查线程是否被中断,就需要重新设置这个状态。
然后,打印出"用户线程被中断"到控制台,表明userThread在执行过程中被中断了。 - 结束信息打印:无论循环是否因为正常完成还是被中断而结束,最后都会打印出"用户线程结束"到控制台,表明userThread的执行已经完成。
启动线程:通过调用userThread.start();,上述定义的线程(userThread)被启动。在start()方法被调用之前,线程只是处于新建状态,并不会执行其Runnable(或实现了Runnable接口的匿名内部类)中的代码。一旦start()方法被调用,JVM就会为userThread分配必要的资源,并使其开始执行Runnable中的代码。
需要注意的是,虽然这里使用了Lambda表达式来创建实现了Runnable接口的匿名内部类实例,但实质上,这段代码做的事情与显式地创建实现了Runnable接口的类并实例化该类的实例,然后将其实例传递给Thread的构造函数是相同的。
Thread.currentThread().interrupt(); 这段代码的作用是让当前正在执行的线程(在这个上下文中,是 userThread)中断自己。这里的 currentThread() 方法返回对当前正在执行的线程对象的引用,因此 Thread.currentThread().interrupt(); 实际上是在调用 userThread 的 interrupt() 方法,从而设置 userThread 的中断状态。
重要的是要理解,中断(interrupting)一个线程并不会立即停止该线程的执行。中断只是设置了一个标志,告诉线程它应该停止正在做的事情,并适当地进行清理。线程本身需要检查这个中断状态(通过调用 Thread.interrupted(),这会清除中断状态,或者通过 Thread.currentThread().isInterrupted(),这不会清除中断状态),并据此决定是否退出或执行其他操作。
在例子中,userThread 在 Thread.sleep(1000); 调用期间可能会被中断(如果其他线程调用了 userThread.interrupt())。如果发生了这种情况,Thread.sleep(1000); 会抛出一个 InterruptedException。在 catch 块中,调用了 Thread.currentThread().interrupt(); 来重新设置中断状态,但这只是为了确保如果后续还有代码需要检查中断状态,它们能够知道线程已经被中断过。这通常是一个好习惯,因为一旦捕获了 InterruptedException,中断状态就会被清除。