仅为方法的第一次调用调用方法块

我有一个方法,在这个方法里面我有一个块:

public void method() { [block instructions] } 

但是这个方法在我的程序中被调用了两次。 我希望这个块只执行一次,并且只对第一次出现的方法执行。 最好和最优雅的方法是什么?

 private static final AtomicBoolean hasRunAtom = new AtomicBoolean(); public void method() { if (hasRunAtom.getAndSet(true)) return; [block instructions] } 

冒着过度工程化的风险,我实际上建议使用状态模式 。 基本上你有一个State抽象:

 interface State extends Runnable {} 

有两个实现:

 class FirstState extends State { public void run() { //[block of code] state = new SecondState(); } } class SecondState extends State { public void run() { //[block instructions] } } 

FirstState切换当前state

 private State state = new FirstState(); 

你的method()现在没有条件逻辑:

 public void method() { state.run(); } 

但是在99%的情况下, boolean标志就足够了……

更新:上面的解决方案不是线程安全的。 如果需要,可以使用简单的AtomicReference state 惯于 就足够了(请参阅下面的Marko Topolnik评论)或者您需要同步整个method()

 public synchronized void method() { state.run(); } 

一个简单的解决方案是使用静态布尔标志:

 static boolean flag = true; public void method() { if (flag) { [block instructions] flag = false; } } 

首先,如果您想要简单快捷的方法,请使用简单的布尔标志(只是不要忘记并发问题并使用@Marko Topolnik解决方案)。

但是如果我们已经开始进行理论讨论并谈论设计模式,而不是像@Tomasz Nurkiewicz那样使用状态模式,我建议考虑单身 (有些人会说它更具反设计模式)以及如何只实现一个此类的实例,因此如果请求此类的实例,则仅在第一次调用中调用构造函数。

如果你想要更多的“开箱即用”解决方案,你可以使用aop

你可能应该重新设计你的方法。 如果某个方法在第二次运行时执行了不同的操作,那么试图理解您的程序的人会感到困惑。

是第二次从程序中的其他地方调用它吗? 如果是这种情况,最简单的方法是将重复的位提取到另一个方法中。

 method() { // Do stuff that's run only the first time method2() } method2() { // Do stuff that's run both times } 

如果从同一个地方调用它,你应该问问自己为什么你的代码期望第二次发生不同的事情。

Marko的答案在概念上很简单,但每次调用方法现在都需要对AtomicBoolean执行primefaces操作。 如果通常调用method(),则会导致显着的性能损失。

这是我提出的另一个基于单例模式的线程安全解决方案。 我希望这会降低性能开销。

 public class MyClass { public void method() { BlockRunner.runIfFirst(); } private static class BlockRunner { static { [block insturctions] } public static void runIfFirst() {} } } 

此解决方案基于此处描述的Singleton lazy-init概念。

如果我的理解是正确的,当首次通过调用runIfFirst()调用BlockRunner时,将调用静态代码块。 将来对runIfFirst()的所有调用都将立即返回,而不会执行任何实际代码。 从性能角度来看,您将通过简单的分支返回操作替换重型primefaces操作。