java - 可运行对象与方法引用和垃圾

标签 java multithreading lambda garbage-collection

相对较新的published article about replacing executors by actors在 Java 8 中声明使用匿名内部类 Runnable 如下所示:

// Functional operation
executor.execute(new Runnable() {
    System.out.println(data);
});

理想情况下可以替换为执行相同操作的对垃圾收集器更友好的技术:

Actor<String> actor = new Actor<>(parentExecutor, ::onMessage);

// Equivalent functional operation
actor.act("Hello world");

public void onMessage(String message) {
   System.out.println(message);
}

这是有道理的 one should generally use method references over anonymous inner classes (即新的Runnable新的Callable)。这个想法已经存在了一段时间了。使用此 Actor 模式似乎还有另一个更有效的微妙之处,但文章中没有明确解释。

我理解使用:

executor.execute(() -> System.out.println(data));

显然效率低下(尽管稍微低效),因为编译器必须创建一个生成的方法invokedynamic“调用站点”并在调用时引用它。

这里的优点是(1)直接方法引用没有invokedynamic方法生成的开销,并且(2)还可以允许您传递方法参数直接引用这个?相对于我们已经使用和了解的模式,本文中提出的这个想法的关键要点是什么?

最佳答案

本文并没有在任何地方说使用 lambda 表达式而不是方法引用会更糟糕。

关键思想是,而不是调用

executor.execute(new Runnable() {
    public void run() {
        System.out.println(data);
    }
});

数百万次,创建数百万个 Runnable 实例,您这样做

Actor<String> actor = new Actor<>(parentExecutor, this::onMessage);

一次并调用

actor.act(data);

数百万次。 Actor 在内部使用字符串队列(或您使用的任何数据项),而不是将任何项包装到另一个对象中,并使用单个 Runnable 进行排队。

这样做时也同样有效

Actor<String> actor = new Actor<>(parentExecutor, x -> System.out.println(x));

相反甚至

Actor<String> actor = new Actor<>(parentExecutor, new ActorListener<String>() {
    public void onMessage(String message) {
        System.out.println(message);
    }
});

由于该代码仅执行一次,因此其技术细节无关紧要。

Lambda 表达式或方法引用使使用此模式变得更容易,但不是此模式的基石。而且这篇文章并没有说别的。它所说的只是“使用 lambda 表达式会变得非常优雅

<小时/>

1 挑剔的是,它在幕后使用了一个 ConcurrentLinkedQueue,它将每个项目包装到一个节点对象中,这表明临时对象可能是多么不相关。使用基于数组的队列会更加一致,但是队列不可能是非阻塞的。鱼与熊掌不可兼得……

关于java - 可运行对象与方法引用和垃圾,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47445188/

相关文章:

java - 为 vaadin 基本条形图中的单个条形着色

java - Spring MVC Controller 无法直接与 Spring Web Flow 连接?

c - 如何避免多个线程写入共享数组导致缓存行失效?

kotlin - 为什么这段代码无法运行,是Kotlin的bug吗?

c++ - 如果在 lambda 中,MSVC 不尊重 constexpr

java - Java 中的 lambda 函数树?

java - 让构造函数正确继承的问题

java - java中使用字符串跳出循环

c# - 如何锁定在多个线程中使用的变量

java - 你如何在 Java 中杀死一个线程?