Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/230.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Exeutor框架的异常处理_Java_Android_Multithreading_Exception - Fatal编程技术网

Java Exeutor框架的异常处理

Java Exeutor框架的异常处理,java,android,multithreading,exception,Java,Android,Multithreading,Exception,我编写了一个android应用程序,用于杀死在后台线程中执行的后台运行进程。我使用下面的类来创建我自己的简单线程框架 public final class ThreadPool { private static final ExecutorService sES = Executors.newCachedThreadPool(); public static Future<?> runNow(Runnable task) { return sES.s

我编写了一个android应用程序,用于杀死在后台线程中执行的后台运行进程。我使用下面的类来创建我自己的简单线程框架

public final class ThreadPool {
    private static final ExecutorService sES = Executors.newCachedThreadPool();

    public static Future<?> runNow(Runnable task) {
        return sES.submit(task);
    }
}
但我仍然有以下问题:

如果使用submitRunnable命令方法,为什么Sun/Oracle决定使用异常而不是将异常传输给用户来处理? 如果我坚持使用submit方法,如何根据自己的需要更改此行为以处理未检查的异常? 我的疑问是:

如果使用submitRunnable命令方法,我知道可以通过Future.get方法获得异常结果。但是,如果我们使用Future.get方法来判断是否发生异常,则位于中的线程Future对象将被阻塞。我想,在大多数情况下,这不是我们所期望的。 我还学习了Executor.execute方法处理类似于common Thread.start的异常。但是没有返回值。因此,任务在任何时候都无法关闭。用户无法通过Future.cancel方法在离开活动时关闭任何正在运行的线程。 如果在将来调用get,如果基础操作callable抛出异常,则将得到ExecutionException

您无法从第1点更改此行为

这种方式实现的原因如下:submit是一个非阻塞调用。作业将在执行器中发布,并在稍后执行。
只有当作业被执行时,你才知道它是否崩溃,因此只有当你试图访问作业结果时,你才会得到异常。

在线程化环境中,未经检查的异常被认为是臭名昭著的,并且会发生奇怪的行为,如线程死亡、没有异常日志等

一个好方法是将可运行对象包装在线程中。创建线程组并将线程添加到线程组

final ThreadGroup group = new ThreadGroup("<a name for the thread group>");

public static Future<?> submitNow(Runnable task) {
   //Create a thread wrapping the runnable task and specify the thread group
   Thread t = new Thread(group,task);
   return sES.submit(task);
}
或者,您可以将UncaughtExceptionHandler分配给当前线程

public class MyUncaughtExceptionHandler implements UncaughtExceptionHandler {

   @Override
   public void uncaughtException(Thread t, Throwable t2) { 
     //Implement
   }
}

Thread.currentThread().setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
或设置默认异常处理程序:

Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());

最后,我找到了一个好的解决办法

我们可以在构造函数中扩展线程并调用setUncaughtHandler,如下所示

public class MyThread1 extends Thread {

public MyThread1(Runnable task) {
    super(task);
    setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            System.out.println("thread throws an uncaught exception at thread id: " + t.getId());
        }
    });
}
}

然后定制一个ThreadFactory,如下所示

    public class MyThreadFactory1 implements ThreadFactory {
        @Override
        public Thread newThread(Runnable r) {
            return new MyThread1(r, "Peace");
        }
}
ExecutorService es = Executors.newSingleThreadExecutor(new MyThreadFactory1());
因此,我们可以在执行器中调用工厂方法,如下所示

    public class MyThreadFactory1 implements ThreadFactory {
        @Override
        public Thread newThread(Runnable r) {
            return new MyThread1(r, "Peace");
        }
}
ExecutorService es = Executors.newSingleThreadExecutor(new MyThreadFactory1());

因此,我们可以检测线程中发生的未捕获异常。

您知道try/catch块吗?@immibis当然知道。那么您有什么建议吗?那么您就知道如何在没有线程的情况下运行Runnable并捕获异常。你可以在另一条线上做,是的。我现在在每个run方法中使用该方法。但是它会带来一些重复编码。try{otherRunnable.run;}catchException e{/*做点什么*/}你知道SUN/ORACLE为什么在Executor框架中以这种方式处理异常吗?它有什么好处吗?我认为如果未检查的异常被安静地消费是不好的。添加了一个简单的解释,解释为什么这样实现。这有一定的意义。但默认行为至少应将异常堆栈跟踪打印到控制台。然而,当事情发生时,它什么也没有显示。为什么?不处理异常,向控制台进行简单打印意味着处理异常。我的意思是,无论如何,你都必须以线程安全的方式访问后台操作的结果,所以你还是要调用get。显然,线程池因为其缺陷而被弃用。@你说的线程池被弃用是什么意思?请至少提供一个链接来证明你对弃用的评论。您所指的具体缺陷是什么?我也没有提到ThreadPool,但我提到了ThreadGroup.1。很抱歉使用了错误的单词ThreadPool。它应该是ThreadGroup。2.下面是您提供的web的第一句话:ThreadGroup是一种将线程组织成层次结构的方法。这个类已经过时了。有关详细信息,请参见有效Java项目73,避免线程组。链接是:@peacepassion-它被认为是过时的,但并没有正式弃用。忘了ThreadGroup吧,我的最后一个建议仍然适用于有效的Java 73:在1.5版之前,只有ThreadGroup API提供了一小部分功能:ThreadGroup.uncaughtException方法是在线程引发未捕获异常时获得控制的唯一方法。例如,此功能对于将堆栈跟踪定向到特定于应用程序的日志非常有用。但是,从1.5版开始,线程的setUncaughtExceptionHandler方法就提供了相同的功能。