2012-08-06 88 views
1

我有一個簡單的問題:爪哇 - 執行方法只有一次

Class A{ 

    B b; 

    public void doSth{ 
     //This method should execute only once 
     b.modify(); //calls doSth() again... 
    } 
} 

在程序運行時,A的一個實例傳遞給B和B調用doSth(如例如回調)。 b.modify使B再次呼叫A.doSth(),這將調用的無限序列。我想實現的是這樣的:我想執行doSth()一次,修改B,然後在下一次執行時以某種方式停止無限制調用鏈並且不執行b.modify

任何建議非常感謝。

+3

爲什麼不使用標誌,你第一次設置爲false? – thegrinner 2012-08-06 13:04:45

+3

您可以實現例如給方法增加一個參數,但這不是更多的設計問題嗎?你想要建模什麼? – twoflower 2012-08-06 13:05:45

+0

根據編碼準則,這將被視爲循環依賴性,應該避免。既然你問了,我們可以在A類中維護一個靜態布爾類型,它只控制一次類A中doSth的執行。 – sundar 2012-08-06 13:06:35

回答

7

添加的狀態標誌類:

​​

使用volatile如果多個線程在起作用。

+0

也許你想清除標誌,否則'doSth'永遠不會再被調用。否則,你可以清除'b = null;'並檢查是否爲空。 – 2012-08-06 13:20:11

+0

不應在實際併發情況下使用此示例。你可以讓兩個線程運行「if」,並且都會傳遞到下一行。 這是更好地在這裏使用CAS,是這樣的:

 private final AtomicBoolean called = new AtomicBoolean(); and then if (!called.compareAndSet(false, true)) return; 
或者如果你喜歡使用「簡單和純潔」的風格,可以使用雙帶同步檢查:
 boolean mayPass = false; if (!called) { synchronized(this) { // or some external object if (!called) { called = true; mayPass = true; } } } if (!mayPass) return; ... 
dchekmarev 2013-12-12 17:16:30

+0

@dchekmarev你說得對!我不能相信我省略了同步......(使方法同步 - 對於這個例子足夠好) – Bohemian 2013-12-13 00:18:08

2

您可以有一個布爾字段,並在您第一次調用該方法時將其設置爲true。

Class A{ 
    boolean isModified = false; 
    B b; 

    public void doSth{ 
     if(!isModified) { 
      this.isModified = true; 
      b.modify(); 
     } 
    } 
} 
+0

不起作用..你必須改變isModified第一 – Razvan 2012-08-06 13:06:14

+0

是的,我糾正它,謝謝。 – Autar 2012-08-06 13:06:53

1

添加boolean alreadyExecuted A類和修改doSmth()的實施

public void doSth{ 
    if(!alreadyExecuted){ 
     alreadyExecuted = true; 
     b.modify(); 

    } 
} 
2

我會嘗試尋找不涉及循環依賴的解決方案。 A和B真的必須引用彼此嗎?在更高的層面上,你想要達到什麼目標?你可以使用A和B對象發佈一些客戶端代碼嗎?

1

認爲這是一個黑客...

使用boolean變量

Class A{ 

    B b; 
    public isOk = true; 

    public void doSth{ 

     if (isOk){ 

     b.modify(); 
     isOk = false; 

     } 

} 
1

也許你應該改變設計不遞歸調用的方法,或者如果你不能只是添加參數,以此來doSth方法

doSth(boolean modify) 
{ 
    if (modify) 
    { 
    b.modify(); 
    } 
    ... 
} 
0

把你的工作在構造函數中

Class A{ 

    B b; 

    A(){ 
     //This should execute only once 
     b.modify(); //calls doSth() again... 
    } 

} 
1

這是「最佳」示例的修補程序,因此無法在併發/多線程情況下真正使用它。你可以讓兩個線程運行「if」,並且都會傳遞到下一行。 這是更好地在這裏使用CAS,是這樣的:

 
private final AtomicBoolean called = new AtomicBoolean(); 

and then 

if (!called.compareAndSet(false, true)) return; 

,或者如果你喜歡使用「簡單和純潔」的風格,採用雙重檢查與同步:

 
private volatile boolean called; 

and then 

boolean mayPass = false; 
if (!called) { 
    synchronized(this) { // or some external object 
    if (!called) { 
     called = true; 
     mayPass = true; 
    } 
    } 
} 
if (!mayPass) return; 
...