如何在JavaFX中对任务进行排队?

如何在JavaFX中对任务进行排队?,java,multithreading,javafx,Java,Multithreading,Javafx,我使用JavaFX制作了一个GUI,有三个单选按钮,一旦用户单击submit并创建另一个线程,根据选中的单选按钮,该线程将运行所需的输出并将结果输出到控制台 但是,当线程运行时(一个进程完成大约需要30秒),我可以检查任何单选按钮。它创建另一个线程,并与另一个正在进行的线程一起输出long。所以我的输出框只是一个杂乱无章的东西!我正在查看异步任务,但我不确定这是否与它有关 我需要的是:如果某个任务正在运行,而我在该任务运行时单击了提交按钮,请等待上一个任务结束,然后执行该任务。 这是我的代码的一

我使用JavaFX制作了一个GUI,有三个单选按钮,一旦用户单击submit并创建另一个线程,根据选中的单选按钮,该线程将运行所需的输出并将结果输出到控制台

但是,当线程运行时(一个进程完成大约需要30秒),我可以检查任何单选按钮。它创建另一个线程,并与另一个正在进行的线程一起输出long。所以我的输出框只是一个杂乱无章的东西!我正在查看异步任务,但我不确定这是否与它有关

我需要的是:如果某个任务正在运行,而我在该任务运行时单击了提交按钮,请等待上一个任务结束,然后执行该任务。

这是我的代码的一个伪代码

类TestMain{
//主要
公共void main(字符串…参数){
发射(args);
}
/*在此处声明名为m_status update的新文本字段*/
/*单击提交按钮后*/{
//创建一个新线程
//运行
}
}
类ThreadBlahBlah实现可运行{
如果选中了(/*第一个复选框*/){
//做这些花哨的事
Platform.runLater(新的Runnable(){
@凌驾
公开募捐{
TestMain.m_status_update.setText(“测试完成!”);
}
});
}如果选中(/*第二个复选框*/),则为else{
//做这些其他花哨的事
Platform.runLater(新的Runnable(){
@凌驾
公开募捐{
TestMain.m_status_update.setText(“测试完成!”);
}
});
}
}

请不要建议我在任务运行时禁用单选按钮,因为我希望将任务按链接列表的方式排列。

当用户单击单选按钮时,请先禁用所有单选按钮,以便用户在任务运行时无法单击其他单选按钮

完成后台作业后,请重新启用所有单选按钮,以便用户可以选择其他任务

请参阅(
RadioButton
extends
Node

如果确实需要对任务进行排队,后台线程应该维护一个任务列表,当用户单击时,将任务添加到列表中,后台线程应该使用该列表(如果当前任务已完成,并且还有更多任务,则启动另一个任务)


有关高级线程执行,请参阅和。

使用单线程执行器运行任务:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
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.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class QueuedTaskExample extends Application {

    private AtomicInteger taskCount = new AtomicInteger(0);

    private ExecutorService exec = Executors.newSingleThreadExecutor(r -> {
        Thread t = new Thread(r);
        t.setDaemon(true); // allows app to exit if tasks are running
        return t ;
    });

    // Use the following if you want the tasks to run concurrently, instead of consecutively:

    // private ExecutorService exec = Executors.newCachedThreadPool(r -> {
    //     Thread t = new Thread(r);
    //     t.setDaemon(true);
    //     return t ;
    // });


    @Override
    public void start(Stage primaryStage) {

        // Just keep track of number of tasks pending/running for a status label:
        IntegerProperty pendingTasks = new SimpleIntegerProperty(0);

        Button startButton = new Button("Start");
        TextArea textArea = new TextArea();
        textArea.setEditable(true);
        startButton.setOnAction(event -> {
            Task<Void> task = createTask();
            // add text to text area if task's message changes:
            task.messageProperty().addListener((obs, oldMessage, newMessage) -> {
                textArea.appendText(newMessage);
                textArea.appendText("\n");
            });

            // for maintaining status label:
            pendingTasks.set(pendingTasks.get()+1);
            task.setOnSucceeded(taskEvent -> pendingTasks.set(pendingTasks.get()-1));

            // run task in single-thread executor (will queue if another task is running):
            exec.submit(task);
        });

        // layout etc
        HBox controls = new HBox(startButton);
        controls.setAlignment(Pos.CENTER);
        controls.setPadding(new Insets(10));

        Label statusLabel = new Label();
        statusLabel.textProperty().bind(Bindings.format("Pending/running tasks: %s", pendingTasks));

        BorderPane root = new BorderPane(textArea, statusLabel, null, controls, null);
        Scene scene = new Scene(root, 600, 400);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    @Override
    public void stop() {
        exec.shutdownNow();
    }

    // Trivial task that counts slowly to 5, updating its message as it goes:
    private Task<Void> createTask() {
        final int taskNumber = taskCount.incrementAndGet();
        return new Task<Void>() {
            @Override 
            public Void call() throws Exception {
                for (int count=1; count<=5; count++) {
                    Thread.sleep(1000);
                    updateMessage("Task "+taskNumber+": Count "+count);
                }
                return null ;
            }
        };
    }

    public static void main(String[] args) {
        launch(args);
    }
}
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
导入java.util.concurrent.AtomicInteger;
导入javafx.application.application;
导入javafx.beans.binding.Bindings;
导入javafx.beans.property.IntegerProperty;
导入javafx.beans.property.SimpleIntegerProperty;
导入javafx.concurrent.Task;
导入javafx.geometry.Insets;
导入javafx.geometry.Pos;
导入javafx.scene.scene;
导入javafx.scene.control.Button;
导入javafx.scene.control.Label;
导入javafx.scene.control.TextArea;
导入javafx.scene.layout.BorderPane;
导入javafx.scene.layout.HBox;
导入javafx.stage.stage;
公共类QueuedTaskExample扩展了应用程序{
私有AtomicInteger任务计数=新的AtomicInteger(0);
private Executor Service exec=Executors.newSingleThreadExecutor(r->{
螺纹t=新螺纹(r);
t、 setDaemon(true);//允许应用程序在任务正在运行时退出
返回t;
});
//如果希望任务同时而不是连续运行,请使用以下命令:
//private ExecutorService exec=Executors.newCachedThreadPool(r->{
//螺纹t=新螺纹(r);
//t.setDaemon(true);
//返回t;
// });
@凌驾
公共无效开始(阶段primaryStage){
//只需跟踪状态标签的挂起/运行任务数:
IntegerProperty pendingTasks=新的SimpleIntegerProperty(0);
按钮开始按钮=新按钮(“开始”);
TextArea TextArea=新建TextArea();
textArea.setEditable(true);
startButton.setOnAction(事件->{
任务Task=createTask();
//如果任务的消息发生更改,请将文本添加到文本区域:
task.messageProperty().addListener((obs、oldMessage、newMessage)->{
textArea.appendText(newMessage);
textArea.appendText(“\n”);
});
//要维护状态标签,请执行以下操作:
pendingTasks.set(pendingTasks.get()+1);
task.setOnSucceeded(taskEvent->pendingTasks.set(pendingTasks.get()-1));
//在单线程执行器中运行任务(如果另一个任务正在运行,则将排队):
执行提交(任务);
});
//布局等
HBox控制=新HBox(启动按钮);
控件。设置对齐(位置中心);
控件。设置填充(新插图(10));
标签状态标签=新标签();
statusLabel.textProperty().bind(Bindings.format(“挂起/正在运行的任务:%s”,pendingTasks));
BorderPane root=新的BorderPane(文本区域、状态标签、null、控件、null);
场景=新场景(root,600400);
初级阶段。场景(场景);
primaryStage.show();
}
@凌驾
公共停车场(){
exec.shutdownNow();
}
//计数缓慢到5的琐碎任务,在执行时更新其消息:
私有任务createTask(){
final int taskNumber=taskCount.incrementAndGet();
返回新任务(){
@凌驾
public Void call()引发异常{

对于(int count=1;count)但是如果我对用户在任务运行时选择单选按钮没有问题,该怎么办?任务应该在上一个任务完成后启动。有点像排队!像链接list@OctavianRox然后你应该在你的后台区域维护一个任务列表