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