InvokeLater冻结GUI

时间:2012-07-25 11:41:04

标签: java multithreading invokelater

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

2 个答案:

答案 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