简体   繁体   English

等待ForkJoin Pool(Java)

[英]Wait in ForkJoin Pool ( Java )

I am using Fork join pool in java for multitasking. 我在java中使用Fork join pool进行多任务处理。 Now i came across a situation where, for every task, I need to hit a url then wait for 10 minutes and then again hit another url to read the data. 现在我遇到了这样一种情况:对于每个任务,我需要点击一个url然后等待10分钟,然后再次点击另一个url来读取数据。 Now the problem is that for those 10 minutes my CPU is idle and not starting another tasks ( more than those defined in fork join pool). 现在的问题是,在那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();
        }
    }

Now What should I do so that CPU picks all the tasks and then wait parallaly for them. 现在我应该怎么做才能让CPU选择所有任务然后等待它们。

Unfortunately, ForkJoinPool does not work well in the face of Thread.sleep() , because it designed for many short tasks that finish quickly, rather than tasks that block for a long time. 不幸的是, ForkJoinPool在面对Thread.sleep()效果不佳,因为它设计用于快速完成的许多短任务,而不是长时间阻塞的任务。

Instead, for what you are trying to accomplish, I would recommend using ScheduledThreadPoolExecutor and dividing your task into two parts. 相反,对于您要完成的任务,我建议使用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");
        }
    }
}

If Java provides a thread pool which allows releasing the underlying resources (that is, the kernel thread participating in the thread pool) during a Thread.sleep() , you should use that instead, but I currently do not know of one. 如果Java提供了一个允许在Thread.sleep()期间释放底层资源(即参与线程池的内核线程)的线程池,那么你应该使用它,但我目前不知道一个。

According to docs forkJoin basic use section tells: 根据docs forkJoin基本用法部分讲述:

if (my portion of the work is small enough) do the work directly else split my work into two pieces invoke the two pieces and wait for the results 如果(我的工作部分足够小)直接进行工作,否则将我的工作分成两部分调用两部分并等待结果

Hopefully this meets your need if you are using 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