如果页面或组件类具有一个非同步对象的实例字段,则为f.ex. ArrayList
,如果对此字段的访问是同步的,则应用程序具有在结构上修改此字段的代码吗?
F.ex:
public class MyPageOrComponent
{
@Persist
private List<String> myList;
void setupRender()
{
if (this.myList == null)
{
this.myList = new ArrayList<>();
}
}
void afterRender(MarkupWriter writer)
{
// Should this be synchronized ?
if (someCondition)
{
this.myList.add(something);
}
else
{
this.myList.remove(something);
}
}
}
我问,因为我似乎明白Tapestry只创建了一个页面或组件类的实例,并且它将这个实例用于所有连接的客户端(但如果不是这样,请纠正我)。
答案 0 :(得分:1)
简而言之,答案是肯定的,你不必这样做,因为Tapestry会为你做这件事。 Tapestry将在运行时为您转换页面和类,这样无论您何时与字段交互,它们实际上都不会处理实例变量,而是处于线程安全的托管变量上。完整的内部工作超出了我的范围,但可以找到对转换的简要参考here。
一个警告,不要在decleration处实例化您的页面/组件变量。我看到了一些奇怪的行为。所以不要这样做:
private List<String> myList = new ArrayList<String>;
答案 1 :(得分:1)
Tapestry使用一些运行时字节代码魔法来转换您的页面和组件。页面和组件是单例,但属性已转换,因此它们由PerThreadValue支持。这意味着每个请求都会获得它自己的值副本,因此不需要同步。
正如@joostschouten所建议的那样,你永远不应该在字段声明中初始化一个可变属性。他讨论的奇怪行为是因为这将由所有请求共享(因为初始化程序仅针对页面/组件单例触发一次)。应该在render方法中初始化可变字段(例如@SetupRender)