代码之家  ›  专栏  ›  技术社区  ›  J.Ober

Java调用任务集合(与invokeAll一样)

  •  0
  • J.Ober  · 技术社区  · 7 年前

    javafx.concurrent.Task java.util.concurrent.Callable ExecutorService.invokeAll(Collection<? extends Callable<T>>) 此方法不能用于任务,因为它们是可运行的,而不是可调用的。

    Executors.callable(Runnable task) 无法工作,因为返回了 Callable 将始终返回null,我需要从 Task.call()

    我理解 Task 不是设计用于 Collections . 但是我需要一个 任务 在我的JavaFX应用程序中,通过编写测试遇到了这个问题。

    除了简单地让我 任务 使生效 ? 我不想这样做,因为我会改变我的代码以适应我的测试。

    1 回复  |  直到 7 年前
        1
  •  2
  •   James_D    7 年前

    您可以将每个任务包装在一个callable中。基本上针对每个 Task<T> task ,您需要 Callable<T> 具体如下:

    Callable<T> callable = () -> {
        task.run();
        return task.getValue();
    };
    

    Function<Task<T>, Callable<T>> 执行此映射的

    Function<Task<T>, Callable<T>> taskWrapper = task -> () -> {
        task.run();
        return task.getValue();
    };
    

    然后给出一个 ExecutorService exec Collection<Task<T>> tasks 你能做到的

    List<Future<T>> results = exec.invokeAll(tasks.stream()
        .map(taskWrapper)
        .collect(Collectors.toList()));
    

    以下是SSCCE:

    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    import java.util.function.Function;
    import java.util.stream.Collectors;
    
    import javafx.application.Application;
    import javafx.concurrent.Task;
    import javafx.geometry.Insets;
    import javafx.geometry.Pos;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.control.Label;
    import javafx.scene.layout.VBox;
    import javafx.stage.Stage;
    
    public class InvokeAllTasks extends Application {
    
        private Random rng = new Random();
        private ExecutorService exec = Executors.newFixedThreadPool(5);
        private Function<Task<Integer>, Callable<Integer>> taskWrapper = task -> () -> {
            task.run();
            return task.getValue();
        };
    
        @Override
        public void start(Stage primaryStage) {
            Button runAll = new Button("Run all tasks");
            Label status = new Label();
    
            runAll.setOnAction(e -> {
                List<Task<Integer>> tasks = createTasks();
    
    
                Task<List<Future<Integer>>> runAllTask = new Task<List<Future<Integer>>>() {
                    @Override
                    protected List<Future<Integer>> call() throws Exception {
                        return exec.invokeAll(tasks.stream().map(taskWrapper).collect(Collectors.toList()));
                    }
                };
                status.setText("Running...");
                runAllTask.setOnSucceeded(evt -> status.setText("All Done"));
                new Thread(runAllTask).start();
    
    
            });
    
            VBox root = new VBox(5, runAll, status);
            root.setMinHeight(120);
            root.setAlignment(Pos.CENTER);
            root.setPadding(new Insets(10));
    
            Scene scene = new Scene(root);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        @Override
        public void stop() {
            exec.shutdown();
        }
    
        private List<Task<Integer>> createTasks() {
            List<Task<Integer>> tasks = new ArrayList<>();
            for (int i = 1 ; i <= 8 ; i++) {
                String name = "Task "+i;
                Task<Integer> t = new Task<Integer>() {
                    @Override
                    protected Integer call() throws Exception {
                        System.out.println(name+" running");
                        Thread.sleep(rng.nextInt(1000)+500);
                        int result = rng.nextInt(500);
                        System.out.println(name+" computed "+result);
                        return result;
                    }
                };
                tasks.add(t);
            }
            return tasks;
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }