マルチスレッドを使用して、単純なサーモスタットをシミュレートしようとしています。サーモスタットは、ユーザーが要求した値 (以下のコードの「最大」値) に到達するために温度を上げる必要があります。私は2つのスレッドを持っています.1つは温度を上げることを担当し、もう1つは温度を下げることを担当しています。減る条件はガス抜き時のみ。しかし、この概念の実装には問題があります。以下のコードが実行されると、2 番目のスレッドが null の例外をスローし続けます。
<pre><code>`private void formWindowActivated(java.awt.event.WindowEvent evt) {
systemInitial();
Thread temperatureUp = new Thread()
{
@Override
public void run()
{
while(true)
{
Max = Integer.parseInt(lblDesiredTemp.getText());
Current = Integer.parseInt(lblCurrentTemp.getText());
try
{
if(Max>Current)
{
lblGasStatus.setText("On");
lblTemperatureSensor.setText("increasing");
increaseTemeture();
}
else
{
lblGasStatus.setText("Off");
if(Current != 0)
lblTemperatureSensor.setText("decreasing");
else
lblTemperatureSensor.setText("----");
}
}
catch(Exception ex)
{
txtLog.setText(ex.getMessage() + "\n" + txtLog.getText() );
}
}
}
};
Thread systemUpdater = new Thread()
{
@Override
public void run()
{
while(true)
{
try
{
notifyGasBoiler(this);
if(Current>0)
decreaseTemeture();
}
catch(Exception ex)
{
txtLog.setText(ex.getMessage() + "\n" + txtLog.getText() );
}
}
}
};
temperatureUp.start();
systemUpdater.start();
}
private synchronized void notifyGasBoiler(Thread gasOff) throws InterruptedException
{
try
{
if("On".equals(lblGasStatus.getText()))
{
gasOff.wait();
txtLog.setText(txtLog.getText() + "\n" + gasOff.getName() + " waits.");
}
else
notifyAll();
}
catch (Exception ex)
{
txtLog.setText(ex.getMessage() + "\n" + txtLog.getText() );
}
}`
ここで何が欠けていますか?
更新I:
これは、システムを実行して取得したログで、2 つの温度を要求します。
温度が 1 に上昇 温度が 2 に上昇 null null null ....
更新 II:
例外に printStackTrace を使用したところ、次のようになりました。
java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at sol.smarthome.GUI.notifyGasBoiler(GUI.java:300)
at sol.smarthome.GUI.access$900(GUI.java:14)
at sol.smarthome.GUI$5.run(GUI.java:276)
アップデートⅢ
<pre><code>`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
{
synchronized (monitor) {
if (!getBoilerStatus())
{
tempUp.wait();
//return;
}
else
{
Max = Integer.parseInt(lblDesiredTemp.getText());
Current = Integer.parseInt(lblCurrentTemp.getText());
if(Max>Current)
{
lblGasStatus.setText("On");
lblTemperatureSensor.setText("increasing");
Thread.sleep(4000);
Current ++;
lblPumpStatus.setText("On");
lblCurrentTemp.setText(String.valueOf(Current));
txtLog.setText("Temperature increased to " + Current + "\n"+ txtLog.getText());
if(Current>8)
lblDanger.setVisible(true);
}
setGasBoilerStatus();
if(!isGasOn)
{
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
//Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
}
lblGasStatus.setText("Off");
if(Current != 0)
lblTemperatureSensor.setText("decreasing");
else
lblTemperatureSensor.setText("----");
}
}
}
}
private synchronized void decreaseTemeture() throws InterruptedException
{
synchronized (monitor) {
if(getBoilerStatus())
{
tempDown.wait();
//return;
}
else
{
Thread.sleep(4000);
if(Current == 0 )
return;
Current --;
lblCurrentTemp.setText(String.valueOf(Current));
lblDanger.setVisible(false);
txtLog.setText("Temperature decreased to " + Current + "\n"+ txtLog.getText());
if(Current<1)
lblPumpStatus.setText("Off");
else
lblPumpStatus.setText("On");
setGasBoilerStatus();
}
}
}
private void systemInitial()
{
lblDanger.setVisible(false);
isPilotOn.setSelected(true);
lblGasStatus.setText("Off");
lblPumpStatus.setText("Off");
isDone = true;
isGasOn = false;
Max = Current = 0;
}
// indicates if the boiler is on (true) or off (false)
// set as volatile to stop caching
private volatile boolean isBoilerOn = false;
protected int Max, Current;
protected boolean isDone, isGasOn, isPumpOn;
private temperatureUp tempUp;
private temperatureDown tempDown;
// Used to synchronize thread access to internal state (Current and
// isBoilerOn member variables. The monitor is private in order
// for this class to encapsulate its synchronization policy.
private final Object monitor = new Object();
// update the bolier's status to on (true) or off (false)
public void setBoilerSatus(boolean status) {
synchronized (monitor) {
// block threads until boiler is switched on
this.isBoilerOn = status;
// (see below), this is the place to notify them...
notifyAll();
}
}
// returns true if the boiler is on, false otherwise
public synchronized boolean getBoilerStatus() {
synchronized (monitor) {
return this.isBoilerOn;
}
}
private void setGasBoilerStatus() {
synchronized (monitor) {
if(Max>Current)
setBoilerSatus(true);
else
setBoilerSatus(false);
}
}
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());
}
}
}
};
`