JavaFx 新线程,具有相同的任务作为输入

标签 java json multithreading javafx task

我正在开发一个 JavaFX 桌面应用程序,我有一个按钮应该从嵌入式设备的内存中读取并将其打印到 JSON 中。我已经实现了一个执行此操作的任务,并且该任务作为参数传递给按钮事件处理程序中的新线程。问题是,这只有效一次。此后,即使单击按钮时生成了新线程,也不会再次调用任务的 call() 方法。这是代码:

任务定义:

Task readValDaemon = new Task<Void>() {
    @Override
    public Void call() {
        //This functions reads from memory and writes the JSON
        readDataHI(connection,commandListHI,statusHI);
        return null;
    }
};

线程创建:

readData.setOnMouseClicked(new EventHandler<MouseEvent>() {
    @Override
    public void handle(MouseEvent event) {

        Thread readValThread = new Thread(readValDaemon);
        readValThread.setDaemon(true);
        readValThread.start();
    }
});

最佳答案

正如其他答案中所观察到的, Task FutureTask 的实现。来自Task文档:

As with FutureTask, a Task is a one-shot class and cannot be reused. See Service for a reusable Worker.

所以你不能重用任务。第二次及后续尝试运行它只会默默地失败。

您可以每次直接创建一个新任务:

private Task<Void> createReadValTask() {
    return new Task<Void>() { 
        @Override
        public Void call() {
            //This functions reads from memory and writes the JSON
            readDataHI(connection,commandListHI,statusHI);
            return null;
        }
    };
}

然后做

readData.setOnMouseClicked(new EventHandler<MouseEvent>() {
    @Override
    public void handle(MouseEvent event) {

        Thread readValThread = new Thread(createReadValTask());
        readValThread.setDaemon(true);
        readValThread.start();
    }
});

您还可以考虑使用 Service ,它是为重用而设计的。它基本上封装了“每次创建一个新任务”的功能,但添加了许多有用的 UI 回调。一个Service还为您管理一个线程池(通过 Executor ),因此您不再需要担心可能创建太多线程。 (如果您想控制它,也可以指定Executor。)

所以,例如:

Service<Void> readValDaemon = new Service<Void>() {
    @Override
    protected Task<Void> createTask() {
        return new Task<Void>() {
            @Override
            public Void call() {
                //This functions reads from memory and writes the JSON
                readDataHI(connection,commandListHI,statusHI);
                return null;
            }
        };
    }
};

然后

readData.setOnMouseClicked(new EventHandler<MouseEvent>() {
    @Override
    public void handle(MouseEvent event) {
        readValThread.restart();
    }
});

如果在服务已经运行时单击鼠标,这将自动取消已经运行的任务,并重新启动一个新任务。如果需要,您可以添加检查,或绑定(bind) disable readData的状态到Service的状态,如果你愿意的话。

关于JavaFx 新线程,具有相同的任务作为输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49275063/

相关文章:

java - Java 套接字中的 HTTP

json - 如何使用 JsonFormat 反序列化 Jackson Json NULL 字符串

javascript - 一项一项获取json项

c++ - 使用boost的多线程一位读者和一位作者

java - 保存我的对象时出现 Hibernate 异常

java - 带有服务的Grails规范测试

json - 使用 Node.js 发布 HTTPS JSON 数据( header +正文)的简单方法

ruby-on-rails - ActionMailer::Base.default_url_options线程安全吗?

c++ - C++中的指针分配是原子的吗?

java - 为什么JVM使用堆来存储对象和静态变量,使用栈来存储局部变量和函数调用?