我正在尝试使用多线程来模拟一个简单的恒温器。恒温器应该升高温度,以达到用户要求的值,该值是下面代码中的“最大”值。我有两个线程,一个负责提高温度,另一个负责降低温度。但减少的条件是它应该只在气体关闭时运行。但我在实施这个概念时遇到了问题。每次我按下向上按钮以增加所需的温度时,GUI会冻结。我该如何解决这个问题?
这就像一个线程持有锁并且不会释放它但是我怎么能注意到哪一个?
`private volatile boolean isBoilerOn = false;
protected int Max, Current;
protected boolean isDone, isGasOn, isPumpOn;
private temperatureUp tempUp;
private temperatureDown tempDown;
public void setBoilerSatus(boolean status) {
this.isBoilerOn = status;
}
public boolean getBoilerStatus() {
return this.isBoilerOn;
}
private synchronized void setGasBoilerStatus() {
if(Max>Current)
setBoilerSatus(true);
else
setBoilerSatus(false);
notifyAll();
}
private void btnUpActionPerformed(java.awt.event.ActionEvent evt) {
if(Max<=8)
{
Max++;
String strI = String.valueOf(Max);
lblDesiredTemp.setText(strI);
setGasBoilerStatus();
}
}
private void btnDownActionPerformed(java.awt.event.ActionEvent evt) {
if(Max>0)
{
Max--;
String strI = String.valueOf(Max);
lblDesiredTemp.setText(strI);
setGasBoilerStatus();
}
}
private void formWindowActivated(java.awt.event.WindowEvent evt) {
systemInitial();
tempUp = new temperatureUp();
tempDown = new temperatureDown();
tempUp.start();
tempDown.start();
}
private synchronized void increaseTemeture() throws InterruptedException
{
while (!getBoilerStatus())
wait();
if(Max>Current)
{
Thread.sleep(4000);
Current ++;
}
setGasBoilerStatus();
}
private synchronized void decreaseTemeture() throws InterruptedException
{
while(getBoilerStatus()) wait();
Thread.sleep(4000);
if(Current == 0 )
return;
Current --;
setGasBoilerStatus();
}
private void systemInitial()
{
isGasOn = false;
Max = Current = 0;
}
class temperatureUp extends Thread
{
@Override
public void run()
{
while(true)
{
try
{
increaseTemeture();
}
catch(Exception ex)
{
StringWriter w = new StringWriter();
ex.printStackTrace(new PrintWriter(w));
txtLog.setText(w + "\n" + txtLog.getText());
}
}
}
};
class temperatureDown extends Thread
{
@Override
public void run()
{
while(true)
{
try
{
decreaseTemeture();
}
catch(Exception ex)
{
StringWriter w = new StringWriter();
ex.printStackTrace(new PrintWriter(w));
txtLog.setText(w + "\n" + txtLog.getText());
}
}
}
};`
答案 0 :(得分:1)
不要使用invokeLater()
来启动/管理/停止Background task
setGasBoilerStatus(); ???
,您遇到问题Concurency in Swing
SwingWorker
未指定重复执行长任务,请改用<{1}}
如果您的任务很简单,并且您只想运行此一次(从JButtons点击),然后使用Runnable#Thread
基本上可以从你的代码中调用SwingWorker
,使用Event Dispatch Thread
只需要更新Swing JComponents,例如代码行invokeLater()
应该包含在{{{ 1}},
因为txtLog.setText(w + "\n" + txtLog.getText());
被声明为invokeLater()
我看到了那些不正确的问题
如果setText()
大约Thread Safe
使用txtLog.setText(w + "\n" + txtLog.getText());
代替JTextArea
为了更好地帮助发布SSCCE演示的问题,mabye还有另一个问题
答案 1 :(得分:0)
这种情况正在发生,因为您没有正确使用invokeLater。看看这里:Java AWT Threads