繁体   English   中英

等待ForkJoin Pool(Java)

[英]Wait in ForkJoin Pool ( Java )

我在java中使用Fork join pool进行多任务处理。 现在我遇到了这样一种情况:对于每个任务,我需要点击一个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选择所有任务然后等待它们。

不幸的是, 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()期间释放底层资源(即参与线程池的内核线程)的线程池,那么你应该使用它,但我目前不知道一个。

根据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));

}

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM