1. 线程中断
线程处于阻塞状态,即调用当前线程的interrupt中断方法,线程是会抛出中断异常的
那么可以用这种方式来介入到运行中的线程,比如发起中断请求,要求当前线程终止运行
因为Java在语言层面,已经彻底抛弃stop语句,即终止当前正在运行的线程的方法,所以你另辟蹊径
package com.yli.thread.demo;
/**
* 线程中断测试:表明线程在阻塞状态期间(调用sleep或者wait方法)</br>
* 如果中断线程,会抛出异常,其实这也是一种介入到运行中线程的设计方法...比如在某种情况下,需要发出指令,终止线程!
*/
public class InterruptTest {
public static void main(String[] args) {
// 启动工作线程
Thread t = new Thread(new Job());
t.start();
try {
System.out.println();
System.err.println("---- 主线程休眠0.5秒,好让job线程确定进入sleep状态 ----");
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
// false
System.out.println("线程中断前的状态:" + t.isInterrupted());
System.out.println("---- 调用job线程中断方法----");
t.interrupt();
}
private static class Job implements Runnable {
@Override
public void run() {
System.out.println("--- begin sleep ---");
// 测试方法一:循环检测中断状态
while(!Thread.currentThread().isInterrupted()) {
System.out.println("-----------线程没有中断-----------");
}
System.out.println("线程中断后的状态:" + Thread.currentThread().isInterrupted());
// 测试方法二:如果处于阻塞状态,调用interrupt方法就会抛出中断异常
// 并且线程的中断状态被清除了:意味着你拿到的 isInterrupt()仍然是false,这里要特别注意!!!
// try {
// Thread.sleep(10000);
// } catch (InterruptedException e) {
// System.out.println("--- job线程收到了中断请求:不过你可以据此做出一些操作 ---");
//
// // false:为什么线程被中断后,还是false状态,因为中断异常后,中断状态被清除
// System.out.println("线程中断后的状态:" + Thread.currentThread().isInterrupted());
// e.printStackTrace();
// }
System.out.println("--- end sleep ---");
}
}
}
2. 线程阻塞与等待
实际上这两个状态是有很大区别的,分别来介绍
(1)阻塞状态
比如线程A和线程B同时持有共享对象obj,线程A已经进入了对象obj的synchronize同步方法,即线程A已经获得了锁
此时线程B也要调用obj的同步方法,由于线程A已经占有了锁,那么线程B在获取这个锁的过程中,处于阻塞状态
(2)等待状态
假设线程A已经获得锁,在运行过程中,发现一些条件不满足(比如转账发现余额不足),那么必须等待余额足够才能继续运行下去。线程A调用对象的wait(3000)方法,即等待3秒钟,看这段时间内是否有资金打入这账户,一旦余额足够,线程A就有机会被唤醒,再次获得锁,就能执行转账操作了。那么从调用wait方法直到线程被唤醒的这个过程中,线程处于等待状态。
特别提醒:很多人还会问到sleep和wait的区别,其实wait明显是会释放锁,而sleep虽然也是进入等待状态,但不会释放锁。这就是最大的区别!!!
简单来概括:阻塞是线程尝试 获得锁 的过程,等待是线程 放弃锁 之后直到被唤醒的过程
3. 线程异常处理器
通常我们catch住异常,并没有做什么特殊处理,或者这种方式也并不那么优雅
可以实现 Thread.UncaughtExceptionHandler 接口,定义自己的异常后处理器
package com.yli.thread.demo;
import java.lang.Thread.UncaughtExceptionHandler;
public class ExceptionTest {
public static void main(String[] args) {
// 启动工作线程
Thread t = new Thread(new Job());
// 启动线程之前设置你的异常后置处理器
t.setUncaughtExceptionHandler(new JobException());
t.start();
}
private static class Job implements Runnable {
@Override
public void run() {
System.out.println("--- begin sleep ---");
System.out.println(10 / 0);
System.out.println("--- end sleep ---");
}
}
private static class JobException implements UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("----捕获到了线程运行时的异常----");
System.out.println("----线程:" + t.getName() + ",异常堆栈信息如下----");
e.printStackTrace();
}
}
}