Java 通过最终方法参数安全发布?
Java并发在实践中描述了几种确保对象安全发布的方法,其中之一是“分配到正确构造的对象的最终字段”。我的问题是,对最终方法参数的赋值是否足以确保安全发布。考虑下面的代码:Java 通过最终方法参数安全发布?,java,multithreading,Java,Multithreading,Java并发在实践中描述了几种确保对象安全发布的方法,其中之一是“分配到正确构造的对象的最终字段”。我的问题是,对最终方法参数的赋值是否足以确保安全发布。考虑下面的代码: private void collectResults() { runOnBackgroundThread(new Runnable() { public void run() { displayResults(someBlockingMethodCall());
private void collectResults() {
runOnBackgroundThread(new Runnable() {
public void run() {
displayResults(someBlockingMethodCall());
}
});
}
private void displayResults(final List<Foo> results) {
runOnUiThread(new Runnable() {
public void run() {
someUiMethodCall(results);
}
});
}
private void collectResults(){
runOnBackgroundThread(新的Runnable(){
公开募捐{
显示结果(someBlockingMethodCall());
}
});
}
私有void显示结果(最终列表结果){
runOnUiThread(新的Runnable(){
公开募捐{
someUiMethodCall(结果);
}
});
}
每个方法都将一个Runnable
排队,以便在另一个线程上执行<在后台线程上调用code>someBlockingMethodCall()以执行某些任务,在UI线程上调用someUiMethodCall()
以显示结果
如果我们假设
someBlockingMethodCall()
返回一个可变的、不同步的列表,例如ArrayList,那么对displayResults()
的最后一个参数赋值是否可以确保安全发布该列表,或者我是否需要采取额外的步骤来确保安全发布?您在这里实际上没有问题。如果您将结果
写入未同步的共享变量,那么您唯一需要担心的就是它
要将它传递给线程,通常应该有一些同步。例如,如果您启动了一个线程,并且结果
被传递给可运行线程,那么线程的开始
就是您需要的同步点
在本例中,您正在调用runOnUiThread
,从您提交结果的那一刻起到线程拾取它的那一刻,就有一个同步点
因此,这里的提交将是线程安全的。这里有一些误解。final
字段发布保证允许程序员假设不可变对象正确工作,即使它们发布不正确。这并不意味着您应该围绕不正确发布的对象设计软件
通常,runOnUiThread
和runOnBackgroundThread
应该以线程安全的方式将Runnable
实例发布到执行线程,因此,不需要依赖最终的
字段发布。这两种方法是否正确,我们无法判断,因为您没有发布它们的代码
此外,正如您正确引用的那样,担保适用于“对正确构造对象的最终字段的赋值”,局部变量(包括参数)不是任何构造对象的字段。但这并不需要担心,因为参数和任何局部变量一样,都是执行方法的线程的局部变量,因此根本不会发布
在创建匿名Runnable
实现的实例时,当您捕获局部变量的值时,这里有一个特例。此捕获实际上具有final
字段分配语义,并且无论参数是否已声明为final
或实际上是final
但是,如前所述,这不应该驱动您的软件设计。您应该确保runOnUiThread
和runOnBackgroundThread
正确发布其可运行项,而不是考虑最终的字段发布。如果这些方法没有正确发布所提供的可运行程序,则可能会出现其他问题,但如果这些方法发布了,则也会正确发布可运行程序引用的任何对象。所有这些都假设您在发布后不修改列表。重要的只是final
字段。对于方法参数和局部变量(基本上是相同的),当您尝试重新分配值时,唯一得到的是一个错误。谢谢John!我没有想到,在后台和UI线程之间传递对象的方法当然必须使用同步,因此该对象可以安全地发布,而无需任何额外的预防措施。@akwizgran很乐意提供帮助。我总是说,当人们对多线程编程有明显的偏执时,他们终于理解了多线程编程:)作为一个新用户,我的投票结果是不可见的,所以我只想说,感谢Holger给出了这一信息丰富的答案,特别是关于捕获字段语义的细节。