java多线程编程核心技术
第七章、拾遗增补
7.1 线程的状态
线程对象在不同的运行时期有不同的状态,状态信息就存在于Thread.State枚举类中。
可以使用Thread.currentThread().getState()方法获取线程状态。
7.2 线程组
可以把线程归属到某一个线程组中,线程组中可以有线程对象,也可以有线程组,组中还可以有线程。这样的组织结构有些类似于树的形式。线程组的作用是,可以批量的管理线程或线程组对象,有效地对线程组或线程组对象进行组织。
7.2.3 线程组自动归属特性
在实例化一个ThreadGroup线程组x时,如果不指定所属的线程组,则x线程组自动归到当前线程对象所属的线程组中,成为它的子线程组。
7.2.6 组内的线程批量停止
当调用线程组ThreadGroup的interrupt()方法时,可以将该组中的所有正在运行的线程批量停止(当然只是做了标记,并不会真的停止)。
7.2.7 递归与非递归取得线程组
示例代码:
ThreadGroup[] listGroup = new ThreadGroup[Thread.currentThread().getThreadGroup().activeCount()];
// 传入true是递归取得子组及子孙组,传入false则只取得子组
boolean recurse = true;
Thread.currentThread().getThreadGroup().enumerate(listGroup, recurse);
7.5 线程中出现异常的处理
方法setUncaughtExceptionHandler()是给指定线程对象设置异常处理器。在Thread类中还可以使用setDefaultUncaughtExceptionHandler()方法对所有线程对象设置异常处理器。
示例代码:
/**
* 线程对象异常处理
*/
public class Test48ThreadException {
public static void main(String[] args) {
// 使用setDefaultUncaughtExceptionHandler来设置线程类的默认的异常处理器
MyThread48.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("线程:" + t.getName() + "出现了异常,被类级别的UncaughtExceptionHandler处理。");
// e.printStackTrace();
}
});
MyThread48 myThread4801 = new MyThread48();
// 使用setUncaughtExceptionHandler方法来设置某个具体线程对象的异常处理器。
myThread4801.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("线程:" + t.getName() + "出现了异常,被对象级别的UncaughtExceptionHandler处理。");
// e.printStackTrace();
}
});
MyThread48 myThread4802 = new MyThread48();
myThread4801.setName("myThread4801");
myThread4802.setName("myThread4802");
myThread4801.start();
myThread4802.start();
/*
从运行结果可以看出,
myThread4801的异常由线程对象调用setUncaughtExceptionHandler方法设置的UncaughtExceptionHandler处理了,
myThread4802的异常由MyThread48类调用的setDefaultUncaughtExceptionHandler方法设置的UncaughtExceptionHandler处理了。
运行结果:
线程:myThread4801出现了异常,被对象级别的UncaughtExceptionHandler处理。
线程:myThread4802出现了异常,被类级别的UncaughtExceptionHandler处理。
*/
}
}
class MyThread48 extends Thread {
@Override
public void run() {
String username = null;
// 这一句一定会抛空指针异常
System.out.println(username.hashCode());
}
}
7.6 线程组内处理异常
我们可以通过继承ThreadGroup类,并重写uncaughtException方法来对某个线程组进行整体的异常处理,例如某个线程出错则停止组内所有线程。
示例代码:
/**
* 线程组对象异常处理
*/
public class Test49ThreadGroupException {
public static void main(String[] args) {
// 使用我们自己实现的ThreadGroup49,其中指定了当某线程出错时,将组内所有线程interrupt的操作
ThreadGroup49 group = new ThreadGroup49("my group");
// 创建几个会一直运行的线程
MyThread49[] myThread49 = new MyThread49[5];
for (int i = 0; i < myThread49.length; i++) {
myThread49[i] = new MyThread49(group, "线程" + i, "1");
myThread49[i].start();
}
// 创建一个会在运行后报错的线程
MyThread49 newT = new MyThread49(group, "报错线程", "a");
newT.start();
/*
从结果可以看出,在抛出异常后,所有线程都收到了interrupt的消息,并由代码控制退出了循环
运行结果:
死循环中:线程4
java.lang.NumberFormatException: For input string: "a"
死循环中:线程3
死循环中:线程3
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
死循环中:线程1
at java.lang.Integer.parseInt(Integer.java:580)
死循环中:线程3
at java.lang.Integer.parseInt(Integer.java:615)
死循环中:线程3
at org.llbqhh.study.java.book.java_multi_thread_programming.MyThread49.run(Test49ThreadGroupException.java:44)
死循环中:线程4
死循环中:线程0
死循环中:线程2
死循环中:线程3
死循环中:线程1
*/
}
}
class ThreadGroup49 extends ThreadGroup {
public ThreadGroup49(String name) {
super(name);
}
/**
* 重写uncaughtException方法,对整组线程进行interrupt操作
* @param t
* @param e
*/
@Override
public void uncaughtException(Thread t, Throwable e) {
super.uncaughtException(t, e);
// 停止整组对线程
this.interrupt();
}
}
class MyThread49 extends Thread {
private String num;
public MyThread49(ThreadGroup group, String name, String num) {
super(group, name);
this.num = num;
}
@Override
public void run() {
int numInt = Integer.parseInt(num);
while (!this.isInterrupted()) {
System.out.println("死循环中:" + Thread.currentThread().getName());
}
}
}
最后
1、所有代码示例都在github中
https://github.com/llbqhh/LlbStudy/tree/master/StudyJava/src/main/java/org/llbqhh/study/java/book/java_multi_thread_programming