如何在Runnable中捕获封闭范围

时间:2016-04-17 18:00:14

标签: java android multithreading

我正在尝试使用下面的类在HandlerThread上进行更新,但我有几个关于变量捕获如何在Java中工作的问题。

[1] 通过引用从封闭范围捕获ret

[2] this引用Runnable,还是从封闭范围内捕获?

[奖励] StartStream应该将Runnable发布到处理程序线程,并且仅在Runnable完成后返回。下面的代码会按预期工作吗?

public class Stream extends HandlerThread {
    Handler handler = null;

    Stream() {
        super("Stream");
        handler = new Handler(getLooper());
        start();
    }

    private int _startStream() { // Start some repeating update
        return 1;
    }

    public int StartStream() {
        int ret = -1;

        handler.post(new Runnable(){
            @Override public void run() {
                synchronized(this) {
                    ret = _startStream();    // [1]
                    this.notify();           // [2]
                }
            }
        });

        synchronized(this) {
            while(ret == -1) {
                try {
                    this.wait();
                }
                catch (InterruptedException e){}
            }
        }

        return ret;
    }
}

2 个答案:

答案 0 :(得分:3)

内部类具有对外部类的隐式引用。

要在匿名内部类中使用ret,它应该是最终的。局部变量不能引用为非final的原因是因为本地类实例在方法返回后可以保留在内存中。它还取决于java version。仍然应该“有效地最终”或将其移动到成员变量。

this指的是Runnable,你应该使用Stream.this来封闭一个。

答案 1 :(得分:1)

ret是一个局部变量,因此需要有效最终。这意味着,如果ret在初始化之后被分配给另一个值,编译器会抱怨。因此[1]导致编译器错误。

这是因为Java语言架构师希望防止局部变量(在方法中声明的变量)从声明它的方法以外的地方更改。

有关封闭方法中变量捕获的更多信息:

this确实引用了Runnable实例。但是,您可以使用Stream.this来引用封闭的Stream实例。