Afflatus
Afflatus

Reputation: 943

InvokeLater Freezes the GUI

I'm trying to simulate a simple thermostat, using multi-threading. The thermostat should increase the temperature in order to reach the value that the user requested for which is "Max" value in the code below. I have two thread, one in charge of increasing the temperature and the other for decreasing it. but the condition for decreasing is it should be only running when the gas is off. but I have a problem with implementing this concept. each time I press the Up button in order to increase the desired temperature the GUI freezes. How can I solve this problem?

It's like a thread is holding the lock and won't release it but how can I notice which one?

`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());
        }
    }
}
};`

Upvotes: 0

Views: 657

Answers (2)

mKorbel
mKorbel

Reputation: 109823

  • don't use invokeLater() for starting / manage / stop the Background task setGasBoilerStatus(); ???, you have issue with Concurency in Swing

  • SwingWorker isn't designated to running long task repeatelly, use Runnable#Thread instead

  • in the case that your task is simple and you want to run this taks only once time (from JButtons click) then to use SwingWorker

  • basically is possible invoke Event Dispatch Thread from your code, required to use invokeLater() but only for update of Swing JComponents, for example code line txtLog.setText(w + "\n" + txtLog.getText()); should be wrapped into invokeLater(),

  • since setText() is declared as Thread Safe I saw there tons questions where that isn't true

  • in the case that txtLog.setText(w + "\n" + txtLog.getText()); is about JTextArea to use append() instead of setText(whatever + getText())

  • for better help sooner post an SSCCE demonstrated issue, mabye there is/are another issue

Upvotes: 1

davidbuzatto
davidbuzatto

Reputation: 9444

This is happening because your are not using invokeLater correctly. Take a look here: Java AWT Threads

Upvotes: 0

Related Questions