2017-06-30 38 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()'的特殊用法确保了适当的全局线程化操作顺序。 –