- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
tableChanged()
对 JTable
线程的调用是否安全,以便我可以从另一个线程调用它,例如完成下载的东西?我想象 tableChanged()
只是将一个新事件放入事件队列中,以便 Event-Dispatcher-Thread 将在将来的某个时候更新 JTable
,但是这样添加线程安全吗?
最佳答案
简短回答不,它不是线程安全的,所有对 tableChanged
的调用都应该在事件调度线程的上下文中进行。
如果您需要更新 TableModel
,请将其与表断开连接并在 EDT 范围内通过单个步骤 (setModel
) 应用它,或者同步通过使用 SwingWorker
或 EventQueue.invokeLater
Swing 的一般经验法则,假设没有任何东西是线程安全的并对其进行保护。
I imagine tableChanged() to just put a new Event into the Event queue, so that the Event-Dispatcher-Thread will update the JTable at some point in the future, but is this adding thread safe?
并非所有事件都安排在事件队列中,许多事件仅由组件内的 for-next
循环处理,直接循环注册的监听器,例如 TableModel
的 fire
事件方法...
例如,从AbstractTableModel
...
public void fireTableChanged(TableModelEvent e) {
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==TableModelListener.class) {
((TableModelListener)listeners[i+1]).tableChanged(e);
}
}
}
这意味着 fireTableChanged
方法将在调用它的线程的上下文中执行,并将从同一线程中通知其监听器。
这意味着如果您要从不同的线程调用 TableModel.setValueAt
,它会调用 fireTableCellUpdated
,这会调用 fireTableChanged
并且最终会在该线程的上下文中调用 tableChanged
...
作为旁注,您不应该直接调用 JTable#tableChanged
,它作为副作用是公开的(在创建 JTable
时内部类不存在; )),您应该修改表的模型并允许模型触发事件通知。
已更新...
考虑这个非常基本的测试...
public class Test {
public static void main(String[] args) {
DefaultTableModel model = new DefaultTableModel(new String[]{"One"}, 1);
model.addTableModelListener(new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
System.out.println("isEventDispatchingThread - " + EventQueue.isDispatchThread());
}
});
model.setValueAt("Test", 0, 0);
}
}
哪个会输出...
isEventDispatchingThread - false
因为更新没有发生在 EDT 内,事实上,它根本没有被事件队列调度......
通过 EDT 的实例化和单独的更新线程进行更新
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
public class Test {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JLabel("Boo"));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
DefaultTableModel model = new DefaultTableModel(new String[]{"One"}, 1);
model.addTableModelListener(new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
System.out.println("isEventDispatchingThread - " + EventQueue.isDispatchThread());
}
});
Thread t = new Thread(new Runnable() {
@Override
public void run() {
model.setValueAt("Test", 0, 0);
}
});
t.start();
}
});
}
}
输出...
isEventDispatchingThread - false
关于java - JTableModelListener.tableChanged() 线程安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25519336/
我是一名优秀的程序员,十分优秀!