Java Android没有正确处理Executor中的AssertionError?

Java Android没有正确处理Executor中的AssertionError?,java,android,exception,threadpoolexecutor,Java,Android,Exception,Threadpoolexecutor,我的测试表明,当AssertionError被抛出到执行器线程中时,Android正在默默地忽略它。logcat中没有打印任何内容,应用程序也不会崩溃。这似乎是错误的,其他人也能复制吗?你知道为什么会发生这种情况,或者有没有解决或修复的方法 这是我的测试: public class TestActivity extends Activity { private final ScheduledExecutorService exec = Executors.newSingleThreadSc

我的测试表明,当AssertionError被抛出到执行器线程中时,Android正在默默地忽略它。logcat中没有打印任何内容,应用程序也不会崩溃。这似乎是错误的,其他人也能复制吗?你知道为什么会发生这种情况,或者有没有解决或修复的方法

这是我的测试:

public class TestActivity extends Activity {

  private final ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    exec.execute(new Runnable() {
      @Override
      public void run() {
        System.err.println("about to fail");
        if (true ) throw new AssertionError();
      }
    });
  }
}

不仅仅是安卓系统;这是(恼人的)bog标准Java行为。可运行线程抛出未捕获异常的ExecutorService线程只是在不记录日志的情况下终止

最简单的解决方法是像这样包装您的Executor-您可以手工完成,也可以创建一个替代Executor服务,您可以在任何地方使用它,而不是使用库存服务:

public class PrintingExecutor implements ExecutorService {
  private final ExecutorService mDelegate;

  public PrintingExecutor (ExecutorService pDelegate) {
    mDelegate = pDelegate;
  }

  @Override
  public Future<?> submit(Runnable task) {
    return mDelegate.submit (new PrintingRunnable(task));
  }

  //override the rest of Executor's methods

  private static class PrintingRunnable implements Runnable {
    private final Runnable mDelegate; 
    public PrintingRunnable (Runnable toRun) {
      mDelegate = toRun;
    }

    @Override
    public void run () {
      try {
        mDelegate.run();
      } catch (Throwable t) {
        t.printStackTrace();
      }
    }
  } 
}
公共类PrintingExecutor实现Executor服务{
私人最终执行人服务mDelegate;
公共打印执行器(执行器服务pDelegate){
mDelegate=pDelegate;
}
@凌驾
公共未来提交(可运行任务){
返回mDelegate.submit(新打印可运行(任务));
}
//重写执行器的其余方法
私有静态类PrintingRunnable实现Runnable{
私人最终可运行mDelegate;
公共打印Runnable(Runnable toRun){
mDelegate=toRun;
}
@凌驾
公开作废运行(){
试一试{
mDelegate.run();
}捕获(可丢弃的t){
t、 printStackTrace();
}
}
} 
}

我相信这个问题是重复和重复的

所以我想我知道现在发生了什么。这不是Android特有的问题,而是通用Java。这个问题与您如何安排服务上的任务有关

如果您使用
execute
,则运行时异常将停止服务线程,VM将通过打印堆栈跟踪并停止整个进程来处理该异常(除非您使用的是
Scheduled
执行器,如果是,请参阅下文)

如果您使用
submit
则返回一个
Future
,当您在该
Future
上调用
get()
时,它将抛出
java.util.concurrent.ExecutionException
,您可以检查该异常以查看发生了什么。在这种情况下,服务将继续处理任务

因此,如果要使用
submit
,或者只使用
execute()
,那么解决方法是确保在
Future
上调用
get()

但是

Executors.newSingleThreadScheduledExecutor()
不同于
Executors.newSingleThreadExecutor)
调度的
执行器带来了更大的复杂性,因为如果线程死亡,它会重新启动线程,并且会以静默方式重新启动。因此,在这种情况下,您需要包装
Runnable

下面是一些代码,演示了它们之间的区别:

  private final ScheduledExecutorService service = Executors.newSingleThreadExecutor();

  public static void testExecuteBomb(ExecutorService service) {
    service.execute(new Runnable() {
      @Override
      public void run() {
        printWithMillis("execute bombing...");
        if (true) throw new RuntimeException("Bomb");
      }
    });

    sleep();

    service.shutdownNow();
  }

  public static void testSubmitBomb(ExecutorService service) {
    try {
      Future t = service.submit(new Runnable() {
        @Override
        public void run() {
          printWithMillis("submit bombing...");
          if (true) throw new RuntimeException("Bomb");
        }
      });

      sleep();

      try {
        printWithMillis(String.valueOf(t.get()));
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    } finally {
      service.shutdownNow();
    }
  }