168 lines
5.1 KiB
Java
168 lines
5.1 KiB
Java
//: concurrency/GreenhouseScheduler.java
|
|
// Rewriting innerclasses/GreenhouseController.java
|
|
// to use a ScheduledThreadPoolExecutor.
|
|
// {Args: 5000}
|
|
import java.util.concurrent.*;
|
|
import java.util.*;
|
|
|
|
public class GreenhouseScheduler {
|
|
private volatile boolean light = false;
|
|
private volatile boolean water = false;
|
|
private String thermostat = "Day";
|
|
public synchronized String getThermostat() {
|
|
return thermostat;
|
|
}
|
|
public synchronized void setThermostat(String value) {
|
|
thermostat = value;
|
|
}
|
|
ScheduledThreadPoolExecutor scheduler =
|
|
new ScheduledThreadPoolExecutor(10);
|
|
public void schedule(Runnable event, long delay) {
|
|
scheduler.schedule(event,delay,TimeUnit.MILLISECONDS);
|
|
}
|
|
public void
|
|
repeat(Runnable event, long initialDelay, long period) {
|
|
scheduler.scheduleAtFixedRate(
|
|
event, initialDelay, period, TimeUnit.MILLISECONDS);
|
|
}
|
|
class LightOn implements Runnable {
|
|
@Override
|
|
public void run() {
|
|
// Put hardware control code here to
|
|
// physically turn on the light.
|
|
System.out.println("Turning on lights");
|
|
light = true;
|
|
}
|
|
}
|
|
class LightOff implements Runnable {
|
|
@Override
|
|
public void run() {
|
|
// Put hardware control code here to
|
|
// physically turn off the light.
|
|
System.out.println("Turning off lights");
|
|
light = false;
|
|
}
|
|
}
|
|
class WaterOn implements Runnable {
|
|
@Override
|
|
public void run() {
|
|
// Put hardware control code here.
|
|
System.out.println("Turning greenhouse water on");
|
|
water = true;
|
|
}
|
|
}
|
|
class WaterOff implements Runnable {
|
|
@Override
|
|
public void run() {
|
|
// Put hardware control code here.
|
|
System.out.println("Turning greenhouse water off");
|
|
water = false;
|
|
}
|
|
}
|
|
class ThermostatNight implements Runnable {
|
|
@Override
|
|
public void run() {
|
|
// Put hardware control code here.
|
|
System.out.println("Thermostat to night setting");
|
|
setThermostat("Night");
|
|
}
|
|
}
|
|
class ThermostatDay implements Runnable {
|
|
@Override
|
|
public void run() {
|
|
// Put hardware control code here.
|
|
System.out.println("Thermostat to day setting");
|
|
setThermostat("Day");
|
|
}
|
|
}
|
|
class Bell implements Runnable {
|
|
@Override
|
|
public void run() { System.out.println("Bing!"); }
|
|
}
|
|
class Terminate implements Runnable {
|
|
@Override
|
|
public void run() {
|
|
System.out.println("Terminating");
|
|
scheduler.shutdownNow();
|
|
// Must start a separate task to do this job,
|
|
// since the scheduler was shut down:
|
|
new Thread() {
|
|
@Override
|
|
public void run() {
|
|
for(DataPoint d : data)
|
|
System.out.println(d);
|
|
}
|
|
}.start();
|
|
}
|
|
}
|
|
// New feature: data collection
|
|
static class DataPoint {
|
|
final Calendar time;
|
|
final float temperature;
|
|
final float humidity;
|
|
public DataPoint(Calendar d, float temp, float hum) {
|
|
time = d;
|
|
temperature = temp;
|
|
humidity = hum;
|
|
}
|
|
@Override
|
|
public String toString() {
|
|
return time.getTime() +
|
|
String.format(
|
|
" temperature: %1$.1f humidity: %2$.2f",
|
|
temperature, humidity);
|
|
}
|
|
}
|
|
private Calendar lastTime = Calendar.getInstance();
|
|
{ // Adjust date to the half hour
|
|
lastTime.set(Calendar.MINUTE, 30);
|
|
lastTime.set(Calendar.SECOND, 00);
|
|
}
|
|
private float lastTemp = 65.0f;
|
|
private int tempDirection = +1;
|
|
private float lastHumidity = 50.0f;
|
|
private int humidityDirection = +1;
|
|
private Random rand = new Random(47);
|
|
List<DataPoint> data = Collections.synchronizedList(
|
|
new ArrayList<>());
|
|
class CollectData implements Runnable {
|
|
@Override
|
|
public void run() {
|
|
System.out.println("Collecting data");
|
|
synchronized(GreenhouseScheduler.this) {
|
|
// Pretend the interval is longer than it is:
|
|
lastTime.set(Calendar.MINUTE,
|
|
lastTime.get(Calendar.MINUTE) + 30);
|
|
// One in 5 chances of reversing the direction:
|
|
if(rand.nextInt(5) == 4)
|
|
tempDirection = -tempDirection;
|
|
// Store previous value:
|
|
lastTemp = lastTemp +
|
|
tempDirection * (1.0f + rand.nextFloat());
|
|
if(rand.nextInt(5) == 4)
|
|
humidityDirection = -humidityDirection;
|
|
lastHumidity = lastHumidity +
|
|
humidityDirection * rand.nextFloat();
|
|
// Calendar must be cloned, otherwise all
|
|
// DataPoints hold references to the same lastTime.
|
|
// For a basic object like Calendar, clone() is OK.
|
|
data.add(new DataPoint((Calendar)lastTime.clone(),
|
|
lastTemp, lastHumidity));
|
|
}
|
|
}
|
|
}
|
|
public static void main(String[] args) {
|
|
GreenhouseScheduler gh = new GreenhouseScheduler();
|
|
gh.schedule(gh.new Terminate(), 5000);
|
|
// Former "Restart" class not necessary:
|
|
gh.repeat(gh.new Bell(), 0, 1000);
|
|
gh.repeat(gh.new ThermostatNight(), 0, 2000);
|
|
gh.repeat(gh.new LightOn(), 0, 200);
|
|
gh.repeat(gh.new LightOff(), 0, 400);
|
|
gh.repeat(gh.new WaterOn(), 0, 600);
|
|
gh.repeat(gh.new WaterOff(), 0, 800);
|
|
gh.repeat(gh.new ThermostatDay(), 0, 1400);
|
|
gh.repeat(gh.new CollectData(), 500, 500);
|
|
}
|
|
} /* (Execute to see output) *///:~
|