1

我针对 Java Google App Engine 1.6.4.1 API 编写了一些代码,为了让我的代码能够编译,我必须处理很多异常,例如 ConcurrentModificationException。我升级到 1.6.5,现在我可以删除大部分异常处理程序,并且我的代码编译得很好。到底是怎么回事?

更新:不再抛出几类异常;因为这可能是由于不同的异常原因而发生的,这里是不再被抛出的异常

  • IllegalArgumentException

  • 非法状态异常

  • 数据存储故障异常

  • 并发修改异常

以下是有人在 GAE 中获得 IllegalArgumentException 的示例:Google App Engine - “java.lang.IllegalArgumentException: 数据存储事务或写入太大。” 这不能再发生了吗?

事务接口文档说您可以在执行 commit() 时获得最后三个中的任何一个:https ://developers.google.com/appengine/docs/java/javadoc/com/google/appengine/api/datastore/交易#commit()

抛出:

java.lang.IllegalStateException - 如果事务已经提交、回滚、提交或回滚正在进行中(通过异步调用),或者尝试提交或回滚已经失败。如果在调用此方法时有任何未完成的异步数据存储调用,则此方法将在这些调用完成后阻塞,然后再继续。

DatastoreFailureException - 如果发生数据存储错误。

java.util.ConcurrentModificationException - 如果其他一些事务同时修改了相同的实体组。

然而,我不再需要处理它们来编译我的代码。这似乎很奇怪。

4

2 回答 2

2

最新版本的 Google App Engine 要求<threadsafe>true</threadsafe>在 appengine-web.xml 中设置属性。在此版本之前,这不是必需的。

当您的应用程序中的一个对象的单个实例同时被多个线程修改时,会发生 ConcurrentModificationExceptions。这当然会导致数据和结果不一致,并且某些类会抛出此异常,以代替返回错误数据或对数据库进行不一致的更改。

将 threadsafe 属性设置为 true,现在可以启用并发请求。

使用并发请求

默认情况下,App Engine 将请求串行发送到给定的网络服务器。您可以通过将元素添加到 appengine-web.xml 来配置 App Engine 以并行发送多个请求:

<threadsafe>true</threadsafe>

在 1.6.5 之前,threadsafe 指令是可选的,在 1.4.3 中引入:

Java applications can enable concurrent request support by setting <threadsafe>
to True in their appengine-web.xml. This flag indicates that request handlers
for your app are thread safe and multiple request handlers may safely run
at the same time in the same memory space for your application.

虽然现在需要这样做,但似乎没有任何立即可用的信息可以解释为什么您的 ConcurrentModificationExceptions 突然消失了。如果您没有按照 1.4.3 发行说明中的​​建议对代码进行更改以使其成为线程安全的,那么这些线程安全问题很可能仍然存在。

以下是博文宣布 App Engine 1.4.3 版本中有关 1.4.3 版本的更多信息:

并发请求:到目前为止,Java 应用程序依赖于启动额外的实例来动态扩展以获得更高的流量水平。现在支持并发请求,每个应用程序实例可以同时服务多个用户请求。首先,确保您的应用程序代码是线程安全的,然后通过将标志添加到您的 appengine-web.xml 来启用并发请求。

如果您报告的异常已经消失,您的代码可能仍然存在一些线程安全问题。您可能看不到这些,因为您增加了实例数量或在应用程序中执行了其他操作来缓解 ConcurrentModificationExceptions。

考虑到 1.6.5 发布不到一个月,我会非常犹豫是否要从我的代码中删除我的异常处理程序。毕竟,他们的工作是检测和处理发生的问题,如果你删除它们,那么你就失去了在它们删除之前可能已经存在的任何优雅降级。

此外,没有某些东西,例如异常,并不构成证明某些东西不会在未来某个未知时间点再次出现。

来自ConcurrentModificationException 的javadocs

当这种修改是不允许的时,检测到对象的并发修改的方法可能会抛出此异常。

例如,通常不允许一个线程在另一个线程对其进行迭代时修改 Collection。一般来说,在这些情况下,迭代的结果是不确定的。如果检测到此行为,某些 Iterator 实现(包括 JRE 提供的所有集合实现的那些)可能会选择抛出此异常。这样做的迭代器被称为快速失败迭代器,因为它们快速而干净地失败,而不是在未来不确定的时间冒着任意的、非确定性的行为的风险。

于 2012-05-19T03:18:15.010 回答
0

我针对 Java Google App Engine 1.6.4.1 API 编写了一些代码,为了让我的代码能够编译,我必须处理很多异常,例如 ConcurrentModificationException。

这里有些奇怪:ConcurrentModificationException 和您列出的其他异常是 RuntimeException 的子类。你永远不需要捕捉那些来满足 Java 编译器。

于 2012-05-24T16:54:55.893 回答