2016-02-27 1 views
2

Что происходит после того, как subtask.fork() возвращает объект ForkJoinTask<Int>? метод compute() вызывался много раз после этого, но откуда и как?ForkJoinTask понимание

Я новичок в Java, и я пытаюсь изучить концепцию fork/join framework. Я видел код ниже онлайн. После чтения Java API я знаю, что subtask.fork() возвращает объект ForkJoinTask<V>, который в этом случае является ForkJoinTask<Int>. Что я не мог понять, что происходит после этого? Вывод указывает, что метод compute() был вызван много раз после этого, но откуда и как?

public class MyRecursiveAction extends RecursiveAction { 

    public static void main(String[] args) { 
     MyRecursiveAction mra1 = new MyRecursiveAction(100); 
     ForkJoinPool fjp1 = new ForkJoinPool(); 
     fjp1.invoke(mra1); 
    } 

    private long workLoad = 0; 

    public MyRecursiveAction(long workLoad) { 
     this.workLoad = workLoad; 
    } 

    @Override 
    protected void compute() { 

     //if work is above threshold, break tasks up into smaller tasks 
     if(this.workLoad > 16) { 
      System.out.println("Splitting workLoad : " + this.workLoad); 

      List<MyRecursiveAction> subtasks = 
       new ArrayList<MyRecursiveAction>(); 

      subtasks.addAll(createSubtasks()); 

      for(RecursiveAction subtask : subtasks){ 
       subtask.fork(); 
      } 

     } else { 
      System.out.println("Doing workLoad myself: " + this.workLoad); 
     } 
    } 

    private List<MyRecursiveAction> createSubtasks() { 
     List<MyRecursiveAction> subtasks = 
      new ArrayList<MyRecursiveAction>(); 

     MyRecursiveAction subtask1 = new MyRecursiveAction(this.workLoad/2); 
     MyRecursiveAction subtask2 = new MyRecursiveAction(this.workLoad/2); 

     subtasks.add(subtask1); 
     subtasks.add(subtask2); 

     return subtasks; 
    } 

} 

Выход:

Splitting workLoad : 100 
Splitting workLoad : 50 
Splitting workLoad : 50 
Splitting workLoad : 25 
Doing workLoad myself: 12 
Doing workLoad myself: 12 
Splitting workLoad : 25 
Doing workLoad myself: 12 
Doing workLoad myself: 12 
Splitting workLoad : 25 
Doing workLoad myself: 12 
Splitting workLoad : 25 
Doing workLoad myself: 12 
Doing workLoad myself: 12 
Doing workLoad myself: 12 

ответ

1

Вам необходимо позвонить invokeAll для того, чтобы расколоть вы работаете на две части, а не делать это вручную, затем 2 новые потоки будут создаваться на «вычислить» свой результат, а затем, если он не достаточно маленький 2 новых потока и т. д.,

Вы не можете предсказать, в каком порядке будет выполняться поток, чтобы порядок сообщений менялся каждый раз, когда вы запускаете этот код.

public class MyRecursiveAction extends RecursiveAction { 

    public static void main(String[] args) { 
     MyRecursiveAction mra1 = new MyRecursiveAction(100); 
     ForkJoinPool fjp1 = new ForkJoinPool(); 
     fjp1.invoke(mra1); 
    } 

    private long workLoad = 0; 

    public MyRecursiveAction(long workLoad) { 
     this.workLoad = workLoad; 
    } 

    @Override 
    protected void compute() { 

     //if work is above threshold, break tasks up into smaller tasks 
     if(this.workLoad > 16) { 
      System.out.println("Splitting workLoad : " + this.workLoad); 

      invokeAll(new MyRecursiveAction(this.workLoad/2), new MyRecursiveAction(this.workLoad/2)); 

     } else { 
      System.out.println("Doing workLoad myself: " + this.workLoad); 
     } 
    } 

} 

Java doc of ForkJoinTask

+0

Большое вам спасибо за помощь. Действительно ценю это. Однако у меня есть еще один вопрос, который я хотел бы, чтобы вы могли мне помочь. После invokeAll (новый MyRecursiveAction (this.workload/2), новый MyRecursiveAction (this.workload/2)), каждый новый созданный объект MyRecursiveAction сразу же вызовет метод MyRecursiveAction.compute() снова? Это верно? – Thor

+1

Не сразу, это будет зависеть, когда их поток активен, но вычисление будет называться да. –

Смежные вопросы