0

我正在尝试使用多线程模拟一个简单的恒温器。恒温器应提高温度以达到用户要求的值,即下面代码中的“最大值”值。我有两个线程,一个负责提高温度,另一个负责降低温度。但减少的条件是它应该只在气体关闭时运行。但我在实施这个概念时遇到了问题。每次我按下向上按钮以增加所需的温度时,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());
        }
    }
}
};`
4

2 回答 2

1
  • 不要invokeLater()用于启动/管理/停止Background task setGasBoilerStatus(); ???,你有问题Concurency in Swing

  • SwingWorker没有指定重复运行长任务,Runnable#Thread而是使用

  • 如果您的任务很简单并且您只想运行一次此任务(从 JButtons 单击)然后使用SwingWorker

  • 基本上可以Event Dispatch Thread从您的代码中调用,需要使用invokeLater()但仅用于更新 Swing JComponents,例如代码行txtLog.setText(w + "\n" + txtLog.getText());应包含在invokeLater(),

  • 因为setText()是声明的,因为Thread Safe我看到了很多不正确的问题

  • txtLog.setText(w + "\n" + txtLog.getText());在即将JTextArea使用的情况下,append()而不是setText(whatever + getText())

  • 为了更快地发布SSCCE演示问题以获得更好的帮助,也许还有另一个问题

于 2012-07-25T12:12:27.090 回答
0

发生这种情况是因为您没有正确使用 invokeLater 。看看这里:Java AWT 线程

于 2012-07-25T11:52:10.750 回答