Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/328.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 googleappengine中请求线程间的环境共享_Java_Google App Engine_Google Cloud Platform - Fatal编程技术网

Java googleappengine中请求线程间的环境共享

Java googleappengine中请求线程间的环境共享,java,google-app-engine,google-cloud-platform,Java,Google App Engine,Google Cloud Platform,我注意到,当我使用GAE提供的请求线程工厂创建新线程时,新线程与父线程具有相同的。(当前环境的identityHashCode在两个线程中是相同的。) 一方面,这很好,因为新创建的线程从与父线程相同的上下文开始。 问题是环境不是一成不变的。它包含用于命名空间处理的“.currentNamespace”属性。如果其中一个线程更改了当前名称空间,它将应用于所有线程,这显然不是我想要的 我解决这个问题的想法是,我创建了一个自己的环境实现,当创建一个新线程时,我将当前环境的内容复制到这个新环境中,并在新

我注意到,当我使用GAE提供的请求线程工厂创建新线程时,新线程与父线程具有相同的。(当前环境的identityHashCode在两个线程中是相同的。)

一方面,这很好,因为新创建的线程从与父线程相同的上下文开始。 问题是环境不是一成不变的。它包含用于命名空间处理的“.currentNamespace”属性。如果其中一个线程更改了当前名称空间,它将应用于所有线程,这显然不是我想要的

我解决这个问题的想法是,我创建了一个自己的环境实现,当创建一个新线程时,我将当前环境的内容复制到这个新环境中,并在新线程上将这个环境设置为当前环境。因此,新线程从相同的上下文开始,但以后可以独立更改

这个解决方案在初始测试期间有效,但后来我遇到了一个问题

Caused by: java.lang.ClassCastException: MyEnvironmentImplementation cannot be cast to com.google.apphosting.runtime.ApiProxyImpl$EnvironmentImpl
    at com.google.apphosting.runtime.ApiProxyImpl.log(ApiProxyImpl.java:67)
我无法访问
com.google.apphosting.runtime.ApiProxyImpl
的代码,但很明显,此方法试图将收到的接口强制转换到自己的实现类中,而不检查类型

我觉得这很奇怪,因为ApiProxy中有一个
void setEnvironmentFactory(ApiProxy.EnvironmentFactory)
,所以人们可能会使用与默认接口不同的
Environment
接口实现

在不同的请求线程中是否有其他方法使用不同的名称空间?
这被认为是一个bug,还是使用我自己的环境实现根本上是错误的

我在JavaSDK的1.9.84中使用AppEngine标准

编辑: 事实上,有文件证明“这不应该从用户代码中使用”
ApiProxy.setEnvironmentForCurrentThread()和ApiProxy.setEnvironmentFactory()方法。因此,我建议的解决办法预计不会奏效。你也不应该尝试类似的东西。

不需要使用谷歌API线程。不要让谷歌API给你带来麻烦。正如我在这里描述的那样,您可以在浏览器之外自己执行此操作

编写一个程序,对浏览器进行子分类,并对打开的每个窗口进行子分类。然后在每个页面上运行javascript,将结果保存到位置栏,以便以后收集。然后从位置栏中收集信息,然后将上一个(位于位置栏中)放回位置栏中,使其看起来与以前相同

如果你想在不同的网页中使用这些数据,那么就通过你的单独程序把它们放在那里

理论上,每个打开的浏览器窗口都可以运行一个单独的GoogleAPI进程

由于您的程序将所有浏览器窗口分别子类化,因此您的程序可以在它们之间共享信息,而不会混淆GoogleAPI

像这样:

编写一个程序(在VB6 sp5中,我几年前就做过。永远不要使用任何更高版本的Visual Studio进行任何操作。在C++11中,这应该可以工作)

在本例中,使用FireFox作为浏览器

(1) 让您的程序启动并为FireFox创建子类

(2) 让您的程序告诉Firefox打开一个新窗口(可能需要将其设置为Firefox的“新选项卡”,也可能不设置)

(3) 告诉您的程序获取新打开窗口的预句柄。快速执行此操作并继续尝试(如果操作系统过载,最多30秒),直到获得预句柄,然后将新窗口的句柄分配给该新窗口或新选项卡

(4) 使用这个新的句柄并向地址栏发送一个javascript(减去“j”),这意味着您向地址栏发送一个完整的“avascript…”,然后添加上一个“j”,因为如果FireFox检测到您在地址栏中放置了带有整个“javascript”的任何命令,它将阻止您执行某些操作(如果我没有记错的话)

(5) 运行javascript,从每个页面获取更改或将更改放入其中

(6) 浏览器中运行javascript的网页完成了部分工作


(7) 不需要使用Google API线程。

为什么需要在上下文中创建线程?只是为了了解您的背景和限制。我有几个用例。最难替换为延迟任务的是,当我需要使用不支持异步请求的客户端库发送多个远程调用时,对结果进行一些处理,然后在每个任务完成后在主线程中收集结果并继续请求。根据您提到的,我会通过GCPs问题跟踪上的功能请求报告这一点。好了,你没有办法在不同的请求线程中使用不同的名称空间,所以最好在那里报告它,以便将来可以将它作为一项功能进行查看。嗨!我不明白这一切与这个问题有什么关系。问题是关于谷歌应用程序引擎。这个解决方案根本不适合这个。