编程语言
首页 > 编程语言> > java – 同步表达式中的方法引用

java – 同步表达式中的方法引用

作者:互联网

对不起伙计们,但我无法理解,同步块内的sync()方法是同步的:

public class TestLambda {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    sync();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }

    static void sync() throws InterruptedException {
        synchronized ((Runnable)TestLambda::new) {
            System.out.println("inside");
            Thread.sleep(1000L);
        }
    }
}

如果在方法引用对象上,为什么我不能只写:
synchronized(TestLambda :: new)? (这将是编译时错误).

有任何想法吗?

UPD:以防万一:它真的是同步的

UPD-2:对于那些怀疑的人,简单的例子:

C:\sandbox\research\learn8\src>"C:\Program Files\Java\jdk1.8.0_31\bin\"javac TestLambda.java
TestLambda.java:27: error: method reference not expected here
    public class Test { { synchronized (Test::new) { System.out.println("sync"); } } }
                                        ^
1 error

解决方法:

让我们看看以下2个作业:

Supplier<TestLambda> supp = TestLambda::new;
Runnable runnable = TestLambda::new;

他们两个编译得很好.基本上因为lambda或方法引用可以与多个功能接口兼容.这意味着,仅仅编写TestLambda :: new并不能告诉我们创建的对象的确切运行时类型.基于目标类型确定实例化哪个接口.并且该目标类型应始终是一个功能接口,在下面的语句中不是这种情况:

synchronized(TestLambda::new) {
}

因此,编译器不允许它,因为运行时将无法决定实例化哪个功能接口.您可以通过将方法引用强制转换为Runnable来提供该信息.所以,在下面的声明中:

synchronized((Runnable) TestLambda::new) {
}

运行时将实例化实现Runnable接口的类的对象.从某种意义上说,铸件给出了方法参考的具体性.

为了给出一个模糊的想法,这可能有点像这样翻译:

class RuntimeClass implements Runnable {
    public void run() {
        TestLambda testLambda = new TestLambda();
    }
}

synchronized(new RuntimeClass()) {
}

P.S:RuntimeClass的实际实例将是单例(因为我们正在使用无状态方法表达式) – 我原来的错误语句

P.P.S:正如@Stuart的评论所指出的那样,无法保证对于lambda或方法引用,是否会创建新实例或返回相同的实例.所以,你不应该同步它们.

标签:method-reference,java,java-8
来源: https://codeday.me/bug/20190824/1710927.html