使用Fork-Join时的静态变量用法

时间:2017-06-30 19:50:51

标签: java fork-join

问题陈述: - //这是一个例子,实际数组大小非常大

假设有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. 假设fork 1计算静态变量aa [2],并假设当fork 2计算aa [2]时,这个fork 2可以获得由fork1计算的值aa [2],或者它将计算seperately ??

  2. 根据我的理解,fork 2在某些情况下很容易访问fork1的aa,假设fork 2想要计算aa [3],它可以得到已经由fork 1计算的值。但是问题假设当fork 1尝试计算aa [4]时,为了计算aa [4],它需要aa [3],哪个fork 1已经计算过,但是如果fork 1试图得到aa [3]则可以,但是很有可能它获得了叉子1的aa [3]的访问权限,而不是计算...再次造成混乱。

  3. 我非常喜欢fork join kindly help

    有一个简单的问题,我想计算一些由同一个类使用的数组,但是在创建多个对象时我想使用由其他对象计算的相同数组,这样我的计算时间就减少了。 /> 如何将该数组复制或获取到另一个对象,以便该对象不需要计算?

1 个答案:

答案 0 :(得分:1)

  
      
  1. 假设fork 1计算静态变量aa [2],并假设当fork 2计算aa [2]时,这个fork 2可以得到值aa [2]   这是由fork1计算的,还是单独计算的?
  2.   

假设两个B任务在不同的线程中运行 - 您选择不执行任何控制 - 这两个线程正在访问同一个数组对象的相同元素而没有任何同步。任何一个线程都可以读取另一个线程写入的值。此外,如果再次访问该数组元素,它们可能会读取不同的值。程序未正确同步,因此无法保证顺序一致性。

  
      
  1. 根据我的理解,fork 2在某些情况下很容易访问fork1的aa,假设fork 2想要计算aa [3],它可以得到的值   已经由fork 1计算了。但问题是假设fork 1   将尝试计算aa [4],为计算aa [4],它需要aa [3],其中   fork 1已经计算过但是如果fork 1试图获得它可能   aa [3],但偶然它可以获得分叉1的aa [3]   不计算......再次造成混乱。
  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提供了该实例(因此他们共享它)。