Java 事件调度线程同步
为了更好地了解EDT同步是如何工作的Java 事件调度线程同步,java,multithreading,swing,junit,Java,Multithreading,Swing,Junit,为了更好地了解EDT同步是如何工作的 及 我已经创建了一个简单的JUnit3测试用例——见下文。目标是等待两个事件: 要创建的GUI/JFrame 文本字段的修改 首先,我对相应的布尔锁对象尝试了wait()调用,但没有按预期工作。然后我尝试了一个循环,等待布尔锁内容。这两种方法都不像我预期的那样有效 如何修改下面的代码以获得预期的等待行为? JUnit测试用例 package com.bitplan.test.common; import javax.swing.JFrame; i
- 及
package com.bitplan.test.common;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import junit.framework.TestCase;
/**
* test the event dispatching thread handling
*
* @author wf
*
*/
public class TestEDT extends TestCase {
private JTextField field;
private Boolean modified=new Boolean(false);
private Boolean created=new Boolean(false);
/**
* test UI handling
*
* @throws InterruptedException
*/
public void testUI() throws InterruptedException {
// see
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
synchronized(created) {
created.wait();
/**
while(!created.isTrue()) {
Thread.sleep(10);
} */
}
field.getDocument().addDocumentListener(new DocumentListener() {
public void flagModification() {
synchronized(modified) {
modified=true;
modified.notify();
}
}
public void insertUpdate(DocumentEvent e) {
flagModification();
}
@Override
public void removeUpdate(DocumentEvent e) {
flagModification();
}
@Override
public void changedUpdate(DocumentEvent e) {
flagModification();
}
});
SwingUtilities.invokeLater(new Runnable() {
public void run() {
updateField("fieldcontent");
}
});
synchronized(modified) {
// https://stackoverflow.com/questions/2536692/a-simple-scenario-using-wait-and-notify-in-java?noredirect=1&lq=1
modified.wait();
/**
while(!modified) {
Thread.sleep(10);
} */
}
}
/**
* update the field with the new content;
*
* @param newContent
*/
protected void updateField(String newContent) {
field.setText(newContent);
}
/**
* create and show the given gui
*/
protected void createAndShowGUI() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Example GUI");
JPanel panel = new JPanel();
field = new JTextField(30);
panel.add(field);
frame.setContentPane(panel);
frame.pack();
frame.setVisible(true);
synchronized(created) {
created=true;
created.notify();
}
}
}
如果使用了“Lock”类,则该方法有效。最初我使用的是布尔值,但这不起作用,因为这些锁对象被赋值替换,例如
created=true.
将创建一个新的单独布尔对象,因此created.notify()会向另一个对象发送信号,并且不会停止主线程中的等待
锁定版本可以工作。我已经将我的问题代码改回了原来错误的布尔版本,以说明这一点
package com.bitplan.test.common;
import java.awt.Frame;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import junit.framework.TestCase;
/**
* test the event dispatching thread handling
*
* @author wf
*
*/
public class TestEDT extends TestCase {
public static class Lock {
boolean value;
public Lock(boolean value) {
super();
this.value = value;
}
/**
* @return the value
*/
public boolean isTrue() {
return value;
}
/**
* @param value the value to set
*/
public void set(boolean value) {
this.value = value;
}
}
private JTextField field;
private Lock modified=new Lock(false);
private Lock created=new Lock(false);
/**
* test UI handling
*
* @throws InterruptedException
*/
public void testUI() throws InterruptedException {
// see
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
synchronized(created) {
while(!created.isTrue())
created.wait();
}
field.getDocument().addDocumentListener(new DocumentListener() {
public void flagModification() {
synchronized(modified) {
modified.set(true);
modified.notify();
}
}
public void insertUpdate(DocumentEvent e) {
flagModification();
}
@Override
public void removeUpdate(DocumentEvent e) {
flagModification();
}
@Override
public void changedUpdate(DocumentEvent e) {
flagModification();
}
});
SwingUtilities.invokeLater(new Runnable() {
public void run() {
updateField("fieldcontent");
}
});
synchronized(modified) {
while(!modified.isTrue())
// http://stackoverflow.com/questions/2536692/a-simple-scenario-using-wait-and-notify-in-java?noredirect=1&lq=1
modified.wait();
}
}
/**
* update the field with the new content;
*
* @param newContent
*/
protected void updateField(String newContent) {
field.setText(newContent);
}
/**
* create and show the given gui
*/
protected void createAndShowGUI() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setTitle("Example GUI");
JPanel panel = new JPanel();
field = new JTextField(30);
panel.add(field);
frame.setContentPane(panel);
frame.pack();
frame.setVisible(true);
synchronized(created) {
created.set(true);
created.notify();
}
}
}
您知道您会注册侦听器来执行要求,对吗?另请参见:您期望的行为是什么?你想干什么?您没有等待锁。注意,created.wait()被notify()中断,Thread.sleep()需要被相应线程上的interrupt()中断。等待10毫秒似乎也不可见。我现在明白了-你在创建的锁上创建了一个死锁。尝试使用create.wait()而不是sleep,并将SwingUtilities.invokeLater放在synchronized语句中(因此省略线程竞争)。最后,需要从AWS线程更新JTextFied。感谢您的评论。我使用Lock类是正确的,但是在引入了这个类之后,我没有尝试等待方法。最初我是和布尔人一起去的,但这并不像下面的答案所解释的那样有效。