1.守护线程
可以通过调用
将线程转换为守护线程
守护线程的唯一用途是为其他线程提供服务。比如计时线程,它定时发送信号给其他线程
当只剩下守护线程时,JVM就退出了。
守护线程应该永远不去访问固有资源,如文件、数据库,因为它会在任何时候甚至在一个操作的中间发生中断
2.未捕获异常处理器
线程的run方法不能抛出任何异常。但是不被检测的异常会导致线程终止
不需要任何的catch子句来处理可以被传播的异常;在线程死亡之前,异常可以被传递给一个用于未捕获异常的处理器
处理器实现了Thread.UncaughtExceptionHandler接口
可以使用setUncaughtExceptionHandler方法为任何一个线程安装一个处理器。也可以使用Thread.setDefaultUncaughtExceptionHandler方法为所有线程安装一个默认的处理器。当然也可以自己重写一个异常处理器,大概出现异常可以给自己发一个Email。
如果不安装默认的处理器,那么默认的处理器为空。如果不为独立的线程安装处理器,此时的处理器就是该线程的ThreadGroup对象
ThreadGroup类实现了Thread.UncaughtExceptionHandler接口,它的uncaughtException方法做如下操作:
1)如果该线程组有父线程组,那么父线程组的uncaughtException方法被调用。
2)否则,如果Thread.getDefaultExceptionHandler方法返回一个非空的处理器,则调用该处理器。
3)否则,如果Throwable是ThreadDeath的一个实例(ThreadDeath对象由stop方法产生,而该方法已过时),什么都不做。
4)否则,线程的名字以及Throwable的栈踪迹被输出到System.err上。
示例(Android中的异常处理器):
public class CrashHandler implements UncaughtExceptionHandler {
private Thread.UncaughtExceptionHandler mDefaultHandler;
public static final String TAG = "CatchExcep";
MainApplication application;
public CrashHandler(MainApplication application){
//获取系统默认的UncaughtException处理器
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
this.application = application;
}
@Override
public void uncaughtException(Thread thread, Throwable ex) {
if(!handleException(ex) && mDefaultHandler != null){
//如果用户没有处理则让系统默认的异常处理器来处理
mDefaultHandler.uncaughtException(thread, ex);
}else{
Intent intent = new Intent(application.getApplicationContext(),
MainActivity.class);
PendingIntent restartIntent = PendingIntent.getActivity(
application.getApplicationContext(), 0, intent,
Intent.FLAG_ACTIVITY_NEW_TASK);
//退出当前程序,跳转到首页 MainActivity.class
AlarmManager mgr = (AlarmManager)application.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000,restartIntent); // 1秒钟后重启应用
application.finishActivity();
}
}
/**
* 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
*
* @param ex
* @return true:如果处理了该异常信息;否则返回false.
*/
private boolean handleException(Throwable ex) {
if (ex == null) {
return false;
}
//使用Toast来显示异常信息
new Thread(){
@Override
public void run() {
Looper.prepare();
Toast.makeText(application.getApplicationContext(), "很抱歉,程序出现异常,即将退出.",
Toast.LENGTH_SHORT).show();
Looper.loop();
}
}.start();
return true;
}
}