Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading TableView未更新来自线程的新信息_Multithreading_Javafx_Tableview - Fatal编程技术网

Multithreading TableView未更新来自线程的新信息

Multithreading TableView未更新来自线程的新信息,multithreading,javafx,tableview,Multithreading,Javafx,Tableview,我为我遇到的问题做了一个小的工作示例程序。请记住,我真正的程序更复杂,所有这些类都是必需的,即使在这个小样本中看起来尺寸过大 主要类别: public class PingTest extends Application { private static final ArrayList<PingThread> THREADS = new ArrayList(); @Override public void start(Stage primaryStage) { Anch

我为我遇到的问题做了一个小的工作示例程序。请记住,我真正的程序更复杂,所有这些类都是必需的,即使在这个小样本中看起来尺寸过大

主要类别:

public class PingTest extends Application {

private static final ArrayList<PingThread> THREADS = new ArrayList();

@Override
public void start(Stage primaryStage) {

    AnchorPane root = new AnchorPane();
    TableView<Map.Entry<String, Ping>> tblPing = new TableView();
    TableColumn<Map.Entry<String, Ping>, String> colName = new TableColumn("Name");
    TableColumn<Map.Entry<String, Ping>, String> colTime = new TableColumn("Time");
    TableColumn<Map.Entry<String, Ping>, String> colDifference = new TableColumn("Difference");

    colName.setCellValueFactory((TableColumn.CellDataFeatures<Map.Entry<String, Ping>, String> p) -> new SimpleStringProperty(p.getValue().getKey()));
    colTime.setCellValueFactory((TableColumn.CellDataFeatures<Map.Entry<String, Ping>, String> p) -> new SimpleStringProperty(Integer.toString(p.getValue().getValue().getTime())));
    colDifference.setCellValueFactory((TableColumn.CellDataFeatures<Map.Entry<String, Ping>, String> p) -> new SimpleStringProperty(Integer.toString(p.getValue().getValue().getDifference())));

    ObservableList<Map.Entry<String, Ping>> items = FXCollections.observableArrayList(Pings.getPings().entrySet());
    tblPing.setItems(items);

    Scene scene = new Scene(root, 300, 750);

    // Align to pane
    AnchorPane.setTopAnchor(tblPing, 0.0);
    AnchorPane.setLeftAnchor(tblPing, 0.0);
    AnchorPane.setRightAnchor(tblPing, 0.0);
    AnchorPane.setBottomAnchor(tblPing, 0.0);

    tblPing.getColumns().addAll(colName, colTime, colDifference);
    root.getChildren().add(tblPing);

    // Setting primary Stage
    primaryStage.setOnCloseRequest(e -> {
        THREADS.forEach(t -> t.interrupt());
    });
    primaryStage.setTitle("Ping List");
    primaryStage.setScene(scene);
    primaryStage.show();

}

public static void main(String[] args) {
    // Some examples
    String[] servers = {"www.google.com", "www.bing.com", "www.yahoo.com", "www.stackoverflow.com"};

    // Start Threads
    for (String server : servers) {
        PingThread pingThread = new PingThread(server);
        pingThread.start();
        THREADS.add(pingThread);
    }
    launch(args);
}
线程

public class PingThread extends Thread {

private final String SERVER;
private int ping = 0;

public PingThread(String server) {
    SERVER = server;
}

@Override
public void run() {
    try {
        while (true) {
            // Ping, update then sleep
            ping();
            Pings.update(SERVER, ping);
            Thread.sleep(1000);
        }
    } catch (InterruptedException ex) {
        // Used to end thread
    }
}

public void ping() {
    try {
        // Sendinging request
        InetAddress host = InetAddress.getByName(SERVER);
        long tm = System.nanoTime();
        Socket so = new Socket(host, 80);
        so.close();
        ping =(int)( (System.nanoTime() - tm) / 1000000L);
    } catch (IOException ex) {
    }

}
}

数据容器

public class Pings {

private static final ConcurrentHashMap<String,Ping> PINGS=  new ConcurrentHashMap();

public static synchronized void update(String server, int time) {
    if (PINGS.containsKey(server)) {
        PINGS.get(server).setTime(time);
    } else {
        PINGS.put(server, new Ping(server,time));
    }
}
public static synchronized ConcurrentHashMap<String,Ping> getPings(){
    return PINGS;
}
}
公共类ping{
私有静态最终ConcurrentHashMap PINGS=新ConcurrentHashMap();
公共静态同步无效更新(字符串服务器,整数时间){
if(PINGS.containsKey(服务器)){
PINGS.get(服务器).setTime(时间);
}否则{
PINGS.put(服务器,新Ping(服务器,时间));
}
}
公共静态同步ConcurrentHashMap getPings(){
返回ping;
}
}

在我的大型实现中,GUI表没有更新为新的值,就像在这个小示例中一样。将值绑定到TableView有什么不对?

此代码存在许多问题

最直接的是电话

FXCollections.observableArrayList(Pings.getPings().entrySet());
创建一个新的可观察列表,并将
Pings.getPings().entrySet()中的所有内容添加到该列表中。但随后修改用于构建它的集合不会修改可观察列表,因此表不会更改。您需要将可观察列表存储在模型中(
Pings
)并直接更新它

您还需要在FX应用程序线程上执行更新,并且需要在
Ping
类中使用JavaFX属性,以便该表可以观察这些值的更改

因此:

必须在FX应用程序线程上更改数据,因此您的数据容器也可以是单线程:

public class Pings {

    private static final Map<String,Ping> PINGS=  new HashMap<>();
    private static final ObservableList<Ping> pingList = FXCollections.observableArrayList();

    public static void update(String server, int time) {
        if (PINGS.containsKey(server)) {
            PINGS.get(server).setTime(time);
        } else {
            Ping ping = new Ping(server, time);
            pingList.add(ping);
            PINGS.put(server, ping);
        }
    }
    public static ObservableList<Ping> getPings(){
        return pingList;
    }

}
最后将表格设置为:

TableView<Ping> tblPing = new TableView<>();
TableColumn<Ping, String> colName = new TableColumn<>("Name");
TableColumn<Ping, Number> colTime = new TableColumn<>("Time");
TableColumn<Ping, Number> colDifference = new TableColumn<>("Difference");

colName.setCellValueFactory(p -> new SimpleStringProperty(p.getValue()));
colTime.setCellValueFactory(p -> p.getValue().timeProperty());
colDifference.setCellValueFactory(p -> p.getValue().differenceProperty());

tblPing.getColumns().addAll(colName, colTime, colDifference);

tblPing.setItems(Pings.getPings());
TableView tblPing=newtableview();
TableColumn colName=新的TableColumn(“名称”);
TableColumn colTime=新的TableColumn(“时间”);
TableColumn colDifference=新的TableColumn(“差异”);
setCellValueFactory(p->newSimpleStringProperty(p.getValue());
setCellValueFactory(p->p.getValue().timeProperty());
colDifference.setCellValueFactory(p->p.getValue().differenceProperty());
tblPing.getColumns().addAll(colName、colTime、colDifference);
tblPing.setItems(Pings.getPings());

非常感谢您的全面解释
public class Pings {

    private static final Map<String,Ping> PINGS=  new HashMap<>();
    private static final ObservableList<Ping> pingList = FXCollections.observableArrayList();

    public static void update(String server, int time) {
        if (PINGS.containsKey(server)) {
            PINGS.get(server).setTime(time);
        } else {
            Ping ping = new Ping(server, time);
            pingList.add(ping);
            PINGS.put(server, ping);
        }
    }
    public static ObservableList<Ping> getPings(){
        return pingList;
    }

}
public class PingThread extends Thread {

    private final String SERVER;

    public PingThread(String server) {
        SERVER = server;
    }

    @Override
    public void run() {
        try {
            while (true) {
                // Ping, update then sleep
                final int ping = ping();
                // again, not exactly sure how you want to handle exceptions...
                if (ping >= 0) {
                    Platform.runLater(() -> Pings.update(SERVER, ping));
                }
                Thread.sleep(1000);
            }
        } catch (InterruptedException ex) {
            // Used to end thread
        }
    }

    public int ping() {
        try {
            // Sendinging request
            InetAddress host = InetAddress.getByName(SERVER);
            long tm = System.nanoTime();
            Socket so = new Socket(host, 80);
            so.close();
            return (int)( (System.nanoTime() - tm) / 1000000L);
        } catch (IOException ex) {
            return -1 ; // or handle exception?
        }

    }

}
TableView<Ping> tblPing = new TableView<>();
TableColumn<Ping, String> colName = new TableColumn<>("Name");
TableColumn<Ping, Number> colTime = new TableColumn<>("Time");
TableColumn<Ping, Number> colDifference = new TableColumn<>("Difference");

colName.setCellValueFactory(p -> new SimpleStringProperty(p.getValue()));
colTime.setCellValueFactory(p -> p.getValue().timeProperty());
colDifference.setCellValueFactory(p -> p.getValue().differenceProperty());

tblPing.getColumns().addAll(colName, colTime, colDifference);

tblPing.setItems(Pings.getPings());