Java多线程(线程组和未处理异常)

Java使用ThreadGroup来表示线程组,它可以对一批线程进行分类管理,Java允许程序直接对线程组进行控制。对线程组的控制相当于同时控制了这批线程。用户创建的所有的线程都属于指定线程组,如果程序没有显示的指定线程属于哪个线程组,则该线程属于默认的线程组。在默认的情况下,子线程和创建它的父线程处于同一个线程组内,例如A线程创建了B线程,并且没有指定B线程的线程组,则B线程属于A线程所在的线程组。

一旦某个线程加入了指定的线程组之后,该线程将一直属于该线程组,直到死亡,线程运行过程中不能改变它所属的线程组。

Thread类提供了如下几个构造方法来设置新创建的线程属于哪个线程组。

  • Thread(ThreadGroup group,Runable target):以target的run方法作为执行体创建线程,属于group组。
  • Thread(ThreadGroup group,Runable target,String name):以target的run方法作为执行体创建新线程,该线程属于group组,且线程名称为name。
  • Thread(ThreadGroup group,String name):创建新的线程,新线程名称为name,属于group组。

因为线程在运行过程中不可改变线程所属的线程组,所以Thread类没有提供setThreadGroup()方法来改变线程所属的线程组,但提供了一个getThreadGroup()方法来返回该线程所属的线程组对象,ThreadGroup类提供了如下两个方法来创建实例对象。

  • ThreadGroup(String name):以指定的线程组名称来创建新的线程组。
  • ThreadGroup(ThreadGroup parent,String name):以指定的名字、指定的父线程组创建了一个新线程组。

上面两个构造方法在创建线程组实例对象时都必须为其指定一个名称,也就是说线程组必须有一个字符串类型的名称,该名称可通过ThreadGroup的getName方法来获取,但不允许改变线程组对象的名称。

ThreadGroup类提供了如下几个常用的方法来操作整个线程组里的所有线程。

  • int activeCount():返回此线程组中活动线程的个数。
  • interrupt():中断线程组中所有线程的执行。
  • isDaemon():判断线程组是否是后台线程组。
  • setDeamon(boolean deamon):把该线程组设置成后台线程组。后台线程组具有一个特征——当后台线程组的最后一个线程执行结束后或最后一个线程被销毁,后台线程组将自动销毁。
  • setMaxPriority(int priority):设置线程组的最高优先级。

ThreadGroup内还定义了一个很有用的方法:void uncaughtException(Thread t,Throwable e),该方法可以处理线程组内任意线程所抛出的未处理的异常。

从Java5开始,Java加强了线程的异常处理,如果线程执行过程中抛出了一个未处理异常,JVM在结束该线程之前会自动查找是否有对应的Thread.UncaughtExceptionHandler对象,如果找到该处理器对象,则会调用该对象的uncaughtException(Thread t,Throwable e)方法来处理异常。

Thread.UncaughtExceptionHandler是Thread类的一个静态内部接口,该接口内只有一个方法:void uncaughtException(Thread t,Throwable e),该方法中的t表示出现异常的线程,而e表示该线程抛出的异常对象。

Thread类提供了如下两个方法来设置异常处理器。

  1. static setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh):为该线程类的所有示例对象设置默认的异常处理器。
  2. setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh):为指定的线程对象设置异常处理器。

ThreadGroup类实现了Thread.UncaughtExceptionHandler接口,所以每个线程所属的线程组将会作为默认的异常处理器。当一个线程抛出未处理异常时,JVM会首先查找线程对象上的异常处理器,如果找到该异常处理器,则将调用异常处理器处理异常,否则,JVM将会调用该线程所属的线程组对象的uncaughtException方法来处理异常。线程组处理异常的默认流程如下。

  1. 如果该线程组有父线程组,则调用父线程组的uncaughtException方法来处理异常。
  2. 如果该线程实例所属的线程类有默认的异常处理器,那么就调用异常处理器来处理异常
  3. 如果异常对象是死亡线程的对象,则不作任何处理;否则,将异常跟踪栈信息打印到System.err错误输出流中,并结束该线程。
public class TestThread extends Thread {
	public static void main(String[] args) throws Exception {
		MyExHandler eh = new MyExHandler();
		Thread.currentThread().setUncaughtExceptionHandler(eh);
		int a = 5 / 0;
		System.out.println("程序结束!");
	}
}

class MyExHandler implements Thread.UncaughtExceptionHandler {
	@Override
	public void uncaughtException(Thread t, Throwable e) {
		System.out.println(t.getName() + "=========" + e.getMessage());
	}
}

 

你可能感兴趣的:(Java,多线程)