【发布时间】:2016-10-29 20:45:24
【问题描述】:
我正在尝试创建一个使用 Swing 测试互斥算法的平台。我的目的是在 GUI 中显示服务器和它们之间发送的消息。我还想显示一个关键部分,显示当前正在访问它的服务器。我正在使用执行 SwingWorker 线程的线程池来部署加载用户选择的互斥算法的服务器。
程序按预期运行,直到我尝试实现消息显示。为了为每条消息显示一个箭头,我扩展了 SwingWorker UIArrowThread,以添加一个 JLabel,该 JLabel 将箭头从源服务器绘制到目标。此线程在删除 JLabel 之前等待 1 秒。当我明确地创建一个或多个这些消息时,这似乎工作正常(我还创建了一个可以创建特定消息的测试平台)。
当我尝试将此 SwingWorker 线程集成到程序中时,问题就出现了。当算法启动时,每个服务器都会尝试访问临界区并将其请求发送到其他每个服务器。这应该调用 UIArrowThread 但似乎只有一些服务器实际创建线程。
public void sendMsg(int destId, Object ... objects) {
comm.sendMsg(destId, objects);
try{
UIArrowThread a = new UIArrowThread(AlgorithmSimulatorUI.jlp,
objects[0].toString(),
comm.getMyId(),
destId);
AlgorithmSimulatorUI.threadPool.execute(a);
} catch (Exception exc){
System.err.println(exc);
}
}
一些服务器似乎只是在实例化 UIArrowThread 之前停止执行并最终造成死锁。任何使其通过该点的服务器都可以正常工作,并且 GUI 会按应有的方式显示。我在调用 UIArrowThread 之前及其构造函数中测试了日志记录。看起来停止执行的线程永远不会在构造函数中进行日志调用。我很困惑为什么会发生这种情况。
public class UIArrowThread extends SwingWorker<Integer, String>{
JLayeredPane jlp;
String type;
int source;
int target;
Point start;
Point end;
Point[] points;
int quadrant;
public UIArrowThread(JLayeredPane jlp, String msg_type, int source,
int target){
this.jlp = jlp;
this.type = msg_type;
this.source = source;
this.target = target;
this.points = getPoints();
this.start = points[0];
this.end = points[1];
}
@Override
protected Integer doInBackground(){
Point lblPoint = getLabelCoordinates(points);
ArrowLabel arrow = new ArrowLabel(type, 1, 2, jlp, points, quadrant);
if (quadrant < 5){
arrow.setBounds(lblPoint.x, lblPoint.y, abs(start.x - end.x),
abs(start.y - end.y));
} else if (quadrant < 7){
arrow.setBounds(lblPoint.x, lblPoint.y, 100, abs(start.y - end.y));
} else {
arrow.setBounds(lblPoint.x, lblPoint.y, abs(start.x - end.x), 100);
}
jlp.add(arrow);
String openHTML = "<html><font color='red',size=12>";
String closeHTML = "</font></html>";
arrow.setText(openHTML + type + closeHTML);
arrow.setHorizontalTextPosition(JLabel.CENTER);
arrow.setVerticalTextPosition(JLabel.CENTER);
jlp.repaint();
try{
Thread.sleep(arrow.lifespan);
} catch (Exception exc){
System.err.println(exc);
} finally {
jlp.remove(arrow);
}
jlp.repaint();
return 1;
}
我添加了我认为与此问题相关的代码部分。如上所述,如果我删除 UIArrowThread,程序将正常运行。
我尝试了更多方法,但仍然产生相同的结果,包括在 process() 中而不是 doInBackground() 中进行工作,以及让 ArrowLabel 从 GUI 中删除自身而不是 UIArrowThread 进行删除。
更新:
我能够让 UI 按预期工作,但仍然不确定最初的问题是什么。该程序有一个消息队列,它在 textPane 中显示来自服务器的消息,所以我想我会在此处使用箭头标签更新 UI。无需更改 ArrowLabel 或 UIArrowThread 的任何现有代码。
【问题讨论】:
标签: java multithreading swing mutex