2017-06-30 37 views
0

問題陳述: - //這是一個示例,實際陣列尺寸很大的靜態變量的使用,同時使用叉加入

假設有A級

public class A{ 
    public static int aa[]=new int[5]; 
    public computeaa(){ 
     for(int i=0;i<5;i++) 
      aa[i] = useaa(i); 
    } 
    //this below function can compute aa[i] value 
    public int useaa(int i){ 
      if(i<=0) 
       return 1; 
      if(aa[i]!=0) 
       return aa[i]; 
      else 
       return useaa[i-1]+useaa[i-2]; 
    } 
} 

而且RecursiveAction B類

@Override 
protected void compute() { 
    // TODO Auto-generated method stub 
    A z=new A(); 
    A.computeaa(); 
} 
public static void main(String[] args) { 
    List<B> tasks =new ArrayList<B>(); 
    for(int i=1; i<=2; i++){ 
     //There is 2 fork will created 
     B =new B(); 
     tasks.add(B); 
     B.fork(); 
    } 
    if (tasks.size() > 0) { 
     for (B task : tasks) { 
      task.join(); 
     } 
    } 
} 

懷疑?

  1. 假設叉1計算靜態變量AA [2],並且假設當叉2將計算AA [2],可以在此叉2得到的值AA [2],其通過與fork1或計算它會單獨計算?

  2. 據我瞭解,fork 2在某些情況下很容易訪問fork1的aa,假設fork 2想要計算aa [3],它可以得到已經由fork 1計算出來的值。但是問題是假設fork 1將嘗試計算aa [4],計算aa [4],它需要aa [3],已經計算出叉1,但如果fork 1試圖獲得aa [3],它可能會有可能,但偶然它會得到訪問權叉1的aa [3],這是不計算...再次造成一團糟。

我很謎題叉聯接好心幫

有簡單的問題,我想計算一些陣列所使用的同一個班級,但是在建立一個以上的對象我想使用相同的數組,這是由其他對象計算,以便減少我的計算時間。
如何複製或獲取該數組到另一個對象,以便該對象不需要計算?

+1

如何使用['AtomicIntegerArray'](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicIntegerArray.html)? –

+0

提示:當您花時間爲我們創建[mcve]時:請遵循遵循Java命名約定的正確有意義的名稱。其他任何東西都會顯着降低您爲我們組合的源代碼的價值。含義 - 單獨使用a和aa和useaa會使您的代碼幾乎無法理解。 – GhostCat

+0

除此之外:沒有人告訴過你,使用靜態在oop中通常是不好的做法嗎? – GhostCat

回答

1
  1. 假設叉1計算靜態變量AA [2],並且假設當叉2將計算AA [2],可以在此叉2得到的值AA [2] ,其通過與fork1計算或它會分開計算?

假設在不同線程中運行兩個B任務 - 在其上選擇不行使任何控制 - 這些兩個線程都訪問同一陣列對象的相同元件而沒有任何同步。任何一個線程都可以讀取另一個寫入的值。而且,如果他們再次訪問該數組元素,他們可能會讀取不同的值。該程序沒有正確同步,因此不能保證順序一致性。

  • 通過我的理解叉2在某些情況下很容易地訪問與fork1的AA,假設叉2想計算AA [3],它可以得到其中 已經由計算的值fork 1.但是問題是假設fork 1 將嘗試計算aa [4],計算aa [4]時,它需要aa [3],其中fork 1已經計算出來了,但如果fork 1試圖得到 aa [3],但偶然它得到aa [3]叉1的訪問,這是 不計算...再次造成一團糟。
  • 是的,你的判斷是正確的 - 關於可能的行爲和關於它是一團糟。

    有簡單的問題,我想計算一些陣列所使用的 同一個班級,但是在建立一個以上的對象我想用它被其他物體計算的 同一陣列,這樣我的計算 時間減少。我如何複製或獲取該數組到另一個對象,所以 ,這個對象不需要計算?

    在某些情況下,您可能會有不同的線程並行計算數組的不相交部分。然而,由於數據之間的依賴關係,問題中提出的計算不適用於此。因爲在計算前2之前沒有可以計算過去索引1的元素,所以元素的計算需要以某種方式進行序列化。你不能通過將單個線程用於工作來實現這一點。

    完成此類計算後,您可以在線程之間共享已初始化的數組,只要它們以某種方式與計算完成同步。如果任何線程在初始計算完成後修改了陣列,則會應用其他同步要求。

    您的具體情況有點棘手,因爲很少有具有同步意義的動作存在。特別是,你的數組元素不是(也不可能是)final,你不能確信你的任務運行的線程只在你使用fork();如果你有後者,那麼主線程之前做的所有事情都會自動與任務的工作同步。正因爲如此,你可能會做這樣的事情:

    public class A { 
        // not static: 
        public int aa[] = new int[5]; 
    
        public void computeAa() { 
         aa[0] = 1; 
         aa[1] = 1; 
    
         for (int i = 2; i < aa.length; i++) { 
          aa[i] = aa[i - 1] + aa[i - 2]; 
         } 
        } 
    
        public int getAa(int i) { 
         return (i < 0) ? 1 : aa[i]; 
        } 
    } 
    
    public class B extends RecursiveAction { 
    
        private A myA; 
    
        public RecursiveAction(A a) { 
         myA = a; 
        } 
    
        @Override 
        protected void compute() { 
         synchronized (myA) { 
          // ensure that myA's initialization is complete 
          while (myA.aa[0] == 0) { 
           // not yet initialized 
           myA.wait(); 
          } 
         } 
         // ... do something with myA (without modifying it) ... 
        } 
    
        public static void main(String[] args) { 
         A theA = new A(); 
    
         synchronized(theA) { 
          // synchronize the initialization of theA, because other threads will 
          // check it 
          theA.computeAa(); 
    
          // wake up any threads waiting on the initialization 
          theA.notifyAll(); 
         } 
    
         List<B> tasks = new ArrayList<B>(); 
    
         for(int i = 1; i <= 2; i++){ 
          //There is 2 fork will created 
          B = new B(theA); 
          tasks.add(B); 
          B.fork(); 
         } 
    
         for (B task : tasks) { 
          task.join(); 
         } 
        } 
    } 
    

    注意這裏說的主線程創建的A實例和分叉任何任務之前對其進行初始化。它爲每個B提供這個實例(因此它們共享它)。

    +0

    computeAa中是否需要在main方法中同步,因爲其他線程只會在for循環中的程序計數器時纔會播放? –

    +0

    答案看起來很完美,你能否清楚我的疑問。 –

    +0

    @MukeshGupta,考慮到所涉及的類只有可用的API文檔沒有理由假設可以安全地省略'synchronized'塊,'wait()'或者'notifyAll()'中的任何一個。特別是,主線程中'fork()'調用的相對時間是不夠的,因爲不同的線程可以看到線程間的動作,例如以不同順序修改共享變量。兩個同步塊一起,以及'wait()'和'notifyAll()'的特殊用法確保了適當的全局線程化操作順序。 –