0 java swing multithreading mutex
我正在尝试使用Swing创建一个测试互斥算法的平台.我的目的是在GUI中显示它们之间发送的服务器和消息.我还想显示一个关键部分,显示当前正在访问它的服务器.我正在使用一个执行SwingWorker线程的线程池来部署加载用户选择的互斥算法的服务器.
程序按预期运行,直到我尝试实现消息显示.为了显示每条消息的箭头,我扩展了SwingWorker,UIArrowThread,以添加一个从源服务器向目标绘制箭头的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);
}
}
Run Code Online (Sandbox Code Playgroud)
有些服务器似乎在实例化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;
}
Run Code Online (Sandbox Code Playgroud)
我已经添加了我觉得这个问题的相关代码部分.如上所述,如果我删除UIArrowThread,程序将正确运行.
我尝试了一些仍然产生相同结果的方法,包括在process()而不是doInBackground()中进行工作,并让ArrowLabel从GUI中移除自己而不是UIArrowThread进行删除.
更新:
我能够按照预期使UI工作,但仍然不能确定原始问题是什么.该程序有一个消息队列,显示来自textPane中服务器的消息,所以我想我会在这里使用箭头标签更新UI.不需要更改ArrowLabel或UIArrowThread的任何现有代码.
您的片段表明您正在使用a ArrowLabel的doInBackground()方法更新Swing组件SwingWorker.这违反了Swing 单线程规则.相反,查询在后台,服务器publish()中期业绩,以及process()他们在EDT,如图审查的例子在这里." SwingWorker的发布和处理方法用于执行中间结果的类型 "的确切表述将取决于您的用例.作为一个具体的例子,这TableSwingWorker扩展了SwingWorker<MyTableModel, RowData>,发布RowData用于更新a的实例TableModel