也许收益 a Consumer
of Event
,所以你产生一些有用的东西,权衡是多一条线consumer.accept
。
Consumer<Event> consumer = switch (event.getEventType()) {
case ORDER -> e -> handle((OrderEvent) e);
case INVOICE -> e -> handle((InvoiceEvent) e);
case PAYMENT -> e -> handle((PaymentEvent) e);
};
consumer.accept(event);
如果您关心性能,请继续
根据有关性能损失的评论,执行基准以比较以下场景:
- 使用消费者和句柄是实例方法
- 使用消费者和句柄是静态方法
- 不使用消费者和句柄是实例方法
- 不使用消费者和句柄是静态方法
查看
- 使用 Consumer 对性能有很大影响吗?
- 静态方法和实例
handle
方法有什么区别吗?
结果是:
# Run complete. Total time: 00:20:30
Benchmark Mode Cnt Score Error Units
SwitchExpressionBenchMark.consumerHandle thrpt 300 49343.496 ± 91.324 ops/ms
SwitchExpressionBenchMark.consumerStaticHandle thrpt 300 49312.273 ± 112.630 ops/ms
SwitchExpressionBenchMark.noConsumerHandle thrpt 300 49353.232 ± 106.522 ops/ms
SwitchExpressionBenchMark.noConsumerStaticHandle thrpt 300 49496.614 ± 122.916 ops/ms
通过观察结果,这4个场景之间没有太大的不同。
- 使用 Consumer 不会对性能产生重大影响。
handle
静态方法和实例方法之间的性能差异可以忽略不计。
执行基准测试:
CPU:Intel(R) Core(TM) i7-8750H
内存:16G
JMH 版本:1.19
VM 版本:JDK 15.0.2
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Thread)
@Warmup(iterations = 30, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 30, time = 500, timeUnit = TimeUnit.MILLISECONDS)
public class SwitchExpressionBenchMark {
public static void main(String[] args) throws Exception {
org.openjdk.jmh.Main.main(args);
}
@Benchmark
public void consumerStaticHandle(Blackhole blackhole, InvoiceEvent invoiceEvent) {
Event event = invoiceEvent;
Consumer<Event> consumer = switch (event.getEventType()) {
case ORDER -> e -> staticHandle((OrderEvent) e);
case INVOICE -> e -> staticHandle((InvoiceEvent) e);
case PAYMENT -> e -> staticHandle((PaymentEvent) e);
};
consumer.accept(event);
}
@Benchmark
public void consumerHandle(Blackhole blackhole, InvoiceEvent invoiceEvent) {
Event event = invoiceEvent;
Consumer<Event> consumer = switch (event.getEventType()) {
case ORDER -> e -> this.handle((OrderEvent) e);
case INVOICE -> e -> this.handle((InvoiceEvent) e);
case PAYMENT -> e -> this.handle((PaymentEvent) e);
};
consumer.accept(event);
}
@Benchmark
public void noConsumerHandle(Blackhole blackhole, InvoiceEvent invoiceEvent) {
Event event = invoiceEvent;
int unused = switch (event.getEventType()) {
case ORDER -> {
this.handle((OrderEvent) event);
yield 0;
}
case INVOICE -> {
this.handle((InvoiceEvent) event);
yield 0;
}
case PAYMENT -> {
this.handle((PaymentEvent) event);
yield 0;
}
};
}
@Benchmark
public void noConsumerStaticHandle(Blackhole blackhole, InvoiceEvent invoiceEvent) {
Event event = invoiceEvent;
int unused = switch (event.getEventType()) {
case ORDER -> {
staticHandle((OrderEvent) event);
yield 0;
}
case INVOICE -> {
staticHandle((InvoiceEvent) event);
yield 0;
}
case PAYMENT -> {
staticHandle((PaymentEvent) event);
yield 0;
}
};
}
private static void staticHandle(PaymentEvent event) {
doSomeJob();
}
private static void staticHandle(InvoiceEvent event) {
doSomeJob();
}
private static void staticHandle(OrderEvent event) {
doSomeJob();
}
private void handle(PaymentEvent event) {
doSomeJob();
}
private void handle(InvoiceEvent event) {
doSomeJob();
}
private void handle(OrderEvent event) {
doSomeJob();
}
private static void doSomeJob() {
Blackhole.consumeCPU(16);
}
private enum EventType {
ORDER, INVOICE, PAYMENT
}
public static class Event {
public EventType getEventType() {
return eventType;
}
public void setEventType(EventType eventType) {
this.eventType = eventType;
}
private EventType eventType;
public double getD() {
return d;
}
public void setD(double d) {
this.d = d;
}
private double d;
}
public static class OrderEvent extends Event {
}
@State(Scope.Thread)
public static class InvoiceEvent extends Event {
@Setup(Level.Trial)
public void doSetup() {
this.setEventType(EventType.INVOICE);
}
}
public static class PaymentEvent extends Event {
}
}