java - 从基于 Swing 的应用程序中的线程(ETC 除外)接收更新

标签 java multithreading swing synchronized volatile

这个问题是关于 volatile 关键字的用法。我有一个 Swing 应用程序,它显示一个表格,并且有一个单独的线程向表格模型添加行。根据this看来我必须将某些字段标记为 volatile ,以确保 EDT 看到对表模型所做的更新。但即使不使列表不稳定,更新似乎也有效。以下是我的代码

import java.awt.BorderLayout;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        JFrame frame = new JFrame("FrameDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        MyTableModel dm = new MyTableModel();
        frame.getContentPane().add(new JScrollPane(new JTable(dm)), BorderLayout.CENTER);

        new Thread(new Runnable() {
            int count = 0;

            @Override
            public void run() {
                while (true) {
                    dm.addElement(count++);
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        frame.pack();
        frame.setVisible(true);
    }

    class Row {
        private String name;
        private String value;

        public Row(String name, String value) {
            super();
            this.name = name;
            this.value = value;
        }

    }

    class MyTableModel extends AbstractTableModel {
        private List<Row> rows = new ArrayList<Test.Row>();

        @Override
        public int getRowCount() {
            return rows.size();
        }

        @Override
        public int getColumnCount() {
            return 2;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            if (columnIndex == 0) {
                return rows.get(rowIndex).name;
            } else if (columnIndex == 1) {
                return rows.get(rowIndex).value;
            } else {
                throw new IllegalArgumentException();
            }
        }

        private void addElement(int i) {
            rows.add(new Row("Name" + i, "Vlaue0" + i));
            fireTableRowsInserted(rows.size() - 1, rows.size() - 1);
        }

        @Override
        public String getColumnName(int column) {
            return column == 0 ? "Name" : "Value";
        }
    }

}

在将rows变量标记为 volatile 之前,我想知道如果我已经可以工作,为什么我必须这样做。而且,上面链接的问题也提到了 synchronized 关键字。我不明白如何使用 synchronized 关键字修复线程看不到最新值的问题。对此的任何解释也表示赞赏。

最佳答案

将调用 dm.addElement(count++); 改为 SwingUtilities.invokeAndWait()

来自javadoc

 * Causes <code>doRun.run()</code> to be executed synchronously on the
 * AWT event dispatching thread.  This call blocks until
 * all pending AWT events have been processed and (then)
 * <code>doRun.run()</code> returns. This method should
 * be used when an application thread needs to update the GUI.
 * It shouldn't be called from the event dispatching thread.
 * Here's an example that creates a new application thread
 * that uses <code>invokeAndWait</code> to print a string from the event
 * dispatching thread and then, when that's finished, print
 * a string from the application thread.
 * <pre>
 * final Runnable doHelloWorld = new Runnable() {
 *     public void run() {
 *         System.out.println("Hello World on " + Thread.currentThread());
 *     }
 * };
 *
 * Thread appThread = new Thread() {
 *     public void run() {
 *         try {
 *             SwingUtilities.invokeAndWait(doHelloWorld);
 *         }
 *         catch (Exception e) {
 *             e.printStackTrace();
 *         }
 *         System.out.println("Finished on " + Thread.currentThread());
 *     }
 * };
 * appThread.start();
 * </pre>

关于java - 从基于 Swing 的应用程序中的线程(ETC 除外)接收更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28893034/

相关文章:

java - JTabbedPane 组件的选项卡未显示

Java - 反射,转换到一个未知的对象?

java - 尝试从相对路径读取文件时获取 "java.io.IOException: Stream closed"

java - 类型不匹配 : Cannot Convert From Void to String in Java

java处理返回异常

python - 慢速网络会导致 Python 应用程序使用*更多* CPU 吗?

java - 关闭模态 JInternalFrame

java - 根据嵌套数组列表的第一个元素对二维数组列表进行排序

c++ - 使用 boost 条件变量 boost scoped_lock 的使用

java - 创建线程后如何将信息传递给线程