【问题标题】:Wait in ForkJoin Pool ( Java )在 ForkJoin 池中等待 (Java)
【发布时间】:2016-12-22 05:51:34
【问题描述】:

我在 Java 中使用 Fork 连接池进行多任务处理。现在我遇到了一种情况,对于每项任务,我需要点击一个 url,然后等待 10 分钟,然后再次点击另一个 url 来读取数据。现在的问题是,在那 10 分钟内,我的 CPU 处于空闲状态,并且没有启动其他任务(比 fork join pool 中定义的任务更多)。

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 选择所有任务,然后并行等待它们。

【问题讨论】:

    标签: java multithreading threadpool cpu fork-join


    【解决方案1】:

    很遗憾,ForkJoinPoolThread.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() 期间释放底层资源(即参与线程池的内核线程),您应该使用它,但我目前不知道有一个。

    【讨论】:

      【解决方案2】:

      根据docsforkJoin 基本使用部分告诉:

      如果(我的工作量足够小) 直接做工作 别的 把我的工作分成两部分 调用这两个部分并等待结果

      如果您使用 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));
      
      }
      

      }

      【讨论】:

        猜你喜欢
        • 2019-09-12
        • 2020-08-11
        • 2019-01-20
        • 1970-01-01
        • 1970-01-01
        • 2019-10-08
        • 2021-01-06
        • 2018-07-24
        • 1970-01-01
        相关资源
        最近更新 更多