为了账号安全,请及时绑定邮箱和手机立即绑定

使用线程发出数据库请求

使用线程发出数据库请求

红糖糍粑 2019-06-18 15:30:46
使用线程发出数据库请求我试图了解线程在java中是如何工作的。这是一个返回ResultSet的简单数据库请求。我在使用JavaFX。    package application;import java.sql.ResultSet;import java.sql.SQLException;import javafx.fxml.FXML;import javafx.scene.control.Button;     import javafx.scene.control.Label;import javafx.scene.control.TextField;public class Controller{     @FXML     private Button getCourseBtn;     @FXML     private TextField courseId;     @FXML     private Label courseCodeLbl;     private ModelController mController;     private void requestCourseName(){         String courseName = "";         Course c = new Course();         c.setCCode(Integer.valueOf(courseId.getText()));         mController = new ModelController(c);         try {             ResultSet rs = mController.<Course>get();             if(rs.next()){                 courseCodeLbl.setText(rs.getString(1));             }         } catch (SQLException e) {             // TODO Auto-generated catch block             e.printStackTrace();         }//      return courseName;     }     public void getCourseNameOnClick(){         try {//              courseCodeLbl.setText(requestCourseName());             Thread t = new Thread(new Runnable(){                 public void run(){                     requestCourseName();                 }             }, "Thread A");             t.start();         } catch (NumberFormatException e) {             // TODO Auto-generated catch block             e.printStackTrace();         }     }}这将返回一个异常:线程“Thread A”中的异常java.lang.IllegalStateException:不在FX应用程序线程上;currentThread=Thread A如何正确地实现线程处理,以便在第二个线程而不是主线程中执行每个数据库请求?我听说过实现Runnable,但是如何在Run方法中调用不同的方法呢?以前从来没有用过线程,但我想是时候开始了。
查看完整描述

3 回答

?
慕尼黑的夜晚无繁华

TA贡献1864条经验 获得超6个赞

线程“Thread A”中的异常java.lang.IllegalStateException:不在FX应用程序线程上;currentThread=Thread A

例外情况是试图告诉您,您正在尝试访问JavaFX应用程序线程之外的JavaFX场景图。但在哪里?

courseCodeLbl.setText(rs.getString(1)); // <--- The culprit

如果我不能这样做,我如何使用背景线程?

这是不同的方法,导致类似的解决方案。

用Platform.runLater包装场景图元素

有一种更简单、最简单的方法是将上面的行封装在Plaform.runLater,以便在JavaFX应用程序线程上执行。

Platform.runLater(() -> courseCodeLbl.setText(rs.getString(1)));

使用任务

这个更好的方法与这些场景一起使用的方法是任务,它具有发送更新的专门方法。在下面的示例中,我将使用updateMessage更新消息。此属性绑定到courseCodeLblTextProperty

Task<Void> task = new Task<Void>() {
    @Override
    public Void call() {
        String courseName = "";
        Course c = new Course();
        c.setCCode(Integer.valueOf(courseId.getText()));
        mController = new ModelController(c);
        try {
            ResultSet rs = mController.<Course>get();
            if(rs.next()) {
                // update message property
                updateMessage(rs.getString(1));
            }
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }}public void getCourseNameOnClick(){
    try {
        Thread t = new Thread(task);
        // To update the label
        courseCodeLbl.textProperty.bind(task.messageProperty());
        t.setDaemon(true); // Imp! missing in your code
        t.start();
    } catch (NumberFormatException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }}


查看完整回答
反对 回复 2019-06-18
?
HUH函数

TA贡献1836条经验 获得超4个赞

这与数据库无关。JavaFX和几乎所有GUI库一样,要求您只使用主UI线程来修改GUI。

您需要将数据从数据库传递回主UI线程。使用Platform.runLater()安排在主UI线程中运行的Runnable。

public void getCourseNameOnClick(){
    new Thread(new Runnable(){
        public void run(){
            String courseName = requestCourseName();
            Platform.runLater(new Runnable(){
                courseCodeLbl.setText(courseName)
            });
        }
    }, "Thread A").start();}

或者,你可以使用任务.


查看完整回答
反对 回复 2019-06-18
  • 3 回答
  • 0 关注
  • 519 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信