自从我不得不处理Java中的并发编程(实际上是并发编程大学课程)以来,已经有很长一段时间了,而且我有一些看似非常基本的问题。下面的示例代码可能看起来有点奇怪,因为我没有使用标准JDK进行UI控件,但它是这样的:
//class Screen
public class Screen{
private Frame rootContainer;
public Screen(Frame rootContainer){
this.rootContainer = rootContainer;
this.createGui();
}
private void createGui(){
Button btn = new Button("Call");
btn.setBounds(20, 20, 100, 20);
rootContainer.add(btn);
btn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ConcurrentDialog cr = createDialog();
cr.start();
//Suposedly only to be called after the Exit button in the dialog is clicked
((Button)e.getSource()).setLabel("Called");
((Button)e.getSource()).repaint();
}
});
}
private ConcurrentDialog createDialog(){
return new ConcurrentDialog(rootContainer, this);
}
}
//Class ConcurrentDialog
public class ConcurrentDialog extends Thread {
private Frame rootContainer;
private Screen screen;
public ConcurrentDialog(Frame rootContainer, Screen screen){
this.rootContainer = rootContainer;
this.screen = screen;
}
public void run(){
createDialog();
synchronized(screen){
try {
screen.wait();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
private void createDialog(){
Dialog dialog = new Dialog(rootContainer, true);
dialog.setBounds(20, 20, 110, 35);
Button btn = new Button("Exit");
btn.setBounds(5, 5, 100, 20);
btn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Button source = (Button)e.getSource();
Dialog dialog = (Dialog)source.getParent();
synchronized(screen){
screen.notify();
}
dialog.dispose();
dialog.getOwner().remove(dialog);
dialog = null;
}
});
dialog.add(btn);
dialog.show();
}
}
在有人问之前,是的,我正在尝试实现一个模态对话框(事实上,我应该将ConcurrentDialog重命名为ModalDialog)。正如我之前所说,我不使用swing(因为我不能......嵌入式VM通常是特定于平台的UI,这是我的情况)并且这个特定的库没有本机模态对话框(意思是没有JOptionPane.showMessageDialog爱我)所以我从头开始构建一个。
无论如何,问题在于:似乎wait()方法的执行时间晚于((Button)e.getSource())。setLabel(“Called”)。我找到的解决方法是将btn设置为具有公共访问权限的全局属性,并将run()方法重构为:
public void run(){
createDialog();
synchronized(screen){
try {
screen.wait();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
screen.getBtn().setLabel("Called");
screen.getBtn().repaint();
}
它以这种方式工作,但在我的“真实世界”场景中,这种实现在耦合方面会造成相当大的混乱。有什么指针吗?
答案 0 :(得分:1)
你的cr.start()会立即返回。
你想要的是把等待(屏幕)放在cr.start()之后,并从run()方法中删除wait(screen)。
这样线程就会显示一个对话框并退出。关闭对话框后,将通知屏幕,并且您的createGui()。actionPerformed()将被唤醒。
答案 1 :(得分:0)
你不能使用swing / awt的多个线程,你不能在运行gui的线程上“等待”,否则它将停止工作。进行涉及gui的异步工作的方法是生成一个单独的线程(就像你正在做的那样),然后让它在需要“更新”gui时使用SwingUtilities.invokeLater()。