簡體   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