Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/331.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 通过最终方法参数安全发布?_Java_Multithreading - Fatal编程技术网

Java 通过最终方法参数安全发布?

Java 通过最终方法参数安全发布?,java,multithreading,Java,Multithreading,Java并发在实践中描述了几种确保对象安全发布的方法,其中之一是“分配到正确构造的对象的最终字段”。我的问题是,对最终方法参数的赋值是否足以确保安全发布。考虑下面的代码: private void collectResults() { runOnBackgroundThread(new Runnable() { public void run() { displayResults(someBlockingMethodCall());

Java并发在实践中描述了几种确保对象安全发布的方法,其中之一是“分配到正确构造的对象的最终字段”。我的问题是,对最终方法参数的赋值是否足以确保安全发布。考虑下面的代码:

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给出了这一信息丰富的答案,特别是关于捕获字段语义的细节。