2016-12-22 35 views
3

我在java中使用叉式连接池进行多任务处理。现在我遇到了一种情况:对于每一项任务,我需要点击一个url然后等待10分钟,然后再次点击另一个url来读取数据。现在的问题是,对于那些10分钟我的CPU空闲,并没有开始另一项任务(超过分叉连接池中定义的那些)。在ForkJoin池中等待(Java)

static ForkJoinPool pool = new ForkJoinPool(10); 
public static void main(String[] args){ 
    List<String> list = new ArrayList<>(); 
    for(int i=1; i<=100; i++){ 
     list.add("Str"+i); 
    } 
    final Tasker task = new Tasker(list); 
    pool.invoke(task); 

public class Tasker extends RecursiveAction{ 

    private static final long serialVersionUID = 1L; 
    List<String> myList; 
    public Tasker(List<String> checkersList) { 
     super(); 
     this.myList = checkersList; 
    } 
    @Override 
    protected void compute() { 
     if(myList.size()==1){ 
      System.out.println(myList.get(0) + "start"); 
      //Date start = new Date(); 
      try { 

        Thread.sleep(10*60*1000); 

      } catch (Exception e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
      System.out.println(myList.get(0) + "Finished"); 
     } 
     else{ 
      List<String> temp = new ArrayList<>(); 
      temp.add( myList.get(myList.size()-1) ); 
      myList.remove(myList.size()-1); 

      Tasker left = new Tasker(myList); 
      Tasker right = new Tasker(temp); 

      left.fork(); 
      right.compute(); 
      left.join(); 
     } 
    } 

现在我该怎么做才能让CPU选择所有的任务,然后等待他们的parallaly。

回答

2

不幸的是,ForkJoinPool在面对Thread.sleep()时效果不佳,因为它设计用于许多短时间完成的短任务,而不是长时间阻塞的任务。

相反,对于您要完成的任务,我会建议使用ScheduledThreadPoolExecutor并将您的任务分为两部分。

import java.util.*; 
import java.util.concurrent.*; 

public class Main { 
    static ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(10); 
    public static void main(String[] args){ 
     for(int i=1; i<=100; i++){ 
      pool.schedule(new FirstHalf("Str"+i), 0, TimeUnit.NANOSECONDS); 
     } 
    } 
    static class FirstHalf implements Runnable { 
     String name; 
     public FirstHalf(String name) { 
      this.name = name; 
     } 
     public void run() { 
      System.out.println(name + "start"); 
      pool.schedule(new SecondHalf(name), 10, TimeUnit.MINUTES); 
     } 
    } 
    static class SecondHalf implements Runnable { 
     String name; 
     public SecondHalf(String name) { 
      this.name = name; 
     } 
     public void run() { 
      System.out.println(name + "Finished"); 
     } 
    } 
} 

如果Java提供了一个线程池,允许释放基础资源(也就是参与线程池内核线程)一Thread.sleep()时,你应该使用,而不是,但我目前不知道的人。

0

根据docs forkJoin基本使用部分讲述:

如果(我工作的一部分是足够小) 做的工作直接 其他 拆我的工作分为两个部分 调用两片等待结果

希望这能满足您的需要,如果你正在使用forkjoin

public class Tasker extends RecursiveAction { 
    static ForkJoinPool pool = new ForkJoinPool(10); 
    static int threshold = 10; 
    public static void main(String[] args){ 
     List<String> list = new ArrayList<>(); 
     for(int i=1; i<=100; i++){ 
      list.add("Str"+i); 
     } 
    final Tasker task = new Tasker(list); 
    pool.invoke(task); 
} 


private static final long serialVersionUID = 1L; 
List<String> myList; 

public Tasker(List<String> checkersList) { 
    super(); 
    this.myList = checkersList; 
} 

void computeDirectly() { 
    for(String url : myList){ 
     System.out.println(url + " start"); 
    } 
    //Date start = new Date(); 
    try { 
     //keep hitting url 
     while (true) { 
      for(String url : myList) { 
       //url hitting code here 
       System.out.println(url + " hitting"); 
      } 
      Thread.sleep(10 * 60 * 1000); 
     } 

    } catch (Exception e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    for(String url : myList){ 
     System.out.println(url + " Finished"); 
    } 
} 

@Override 
protected void compute() { 
    if (myList.size() <= threshold) { 
     computeDirectly(); 
     return; 
    } 

    //temp list have only one url 
    //List<String> temp = new ArrayList<>(); 
    //temp.add( myList.get(myList.size()-1) ); 
    //myList.remove(myList.size()-1); 


    //Tasker left = new Tasker(myList); 
    //Tasker right = new Tasker(temp); 


    //left.fork(); 
    //right.compute(); 
    //left.join(); 

    List<String> first = new ArrayList<>(); 
    List<String> second = new ArrayList<>(); 

    //divide list 
    int len = myList.size(); 
    int smHalf = len/2;//smaller half 

    first = myList.subList(0, smHalf); 
    second = myList.subList(smHalf + 1, len); 

    invokeAll(new Tasker(first), new Tasker(second)); 

} 

}