DelayQueue实例-《Java编程思想》并发习题33

习题33要求利用DelayQueue实现书中例子GreenhouseScheduler。后文程序我参考书中例子DelayQueueDemo完成的,运行结果如后文所示,与原GreenhouseScheduler基本一致,但是LightOn类似乎会少运行几次。

不知何种原因导致这种结果,还请javaeye的高手们指点!
----------------------------------------------------------------
package concurrency;
/*Exercise 33: (7) Modify GreenhouseScheduler.java so that it uses a DelayQueue instead of a ScheduledExecutor.*/
import static java.util.concurrent.TimeUnit.*;
import static net.mindview.util.Print.*;
import java.util.concurrent.*;
import java.util.*;

//定义用于DelayQueue的父类
class DTask implements Runnable, Delayed{
private int delay=0;
private long initialDelay, period;
private long trigger;
DTask(long initialDelay, long period){
this.initialDelay=initialDelay;
this.period=period;
trigger=System.nanoTime() + NANOSECONDS.convert(initialDelay, MILLISECONDS);
}
public long getDelay(TimeUnit unit) {
return unit.convert(
trigger - System.nanoTime(), NANOSECONDS);
}
public void setDelay(){
//此处设置Delay,使得DelayedTaskConsumer消费后延迟时间trigger增加period;
trigger=System.nanoTime() + NANOSECONDS.convert(period, MILLISECONDS);
}
public int compareTo(Delayed arg) {
DTask that = (DTask)arg;
if(trigger < that.trigger) return -1;
if(trigger > that.trigger) return 1;
return 0;
}
public void run() {try {
TimeUnit.MILLISECONDS.sleep(period);
} catch (InterruptedException e) {
print("sleep interrupted");
}}
}
//主类GreenhouseScheduler33,通过一系列DTask的子类实现
//开关灯、调温等操作
public class GreenhouseScheduler33 {
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;
}
//LightOn
class LightOn extends DTask {
LightOn(long initialDelay, long period) {
super(initialDelay, period);
}
public void run() {
super.run();
// Put hardware control code here to
// physically turn on the light.
System.out.println("Turning on lights");
light = true;
}
}
class LightOff extends DTask {
LightOff(long initialDelay, long period) {
super(initialDelay, period);
}

public void run() {
// Put hardware control code here to
// physically turn off the light.
System.out.println("Turning off lights");
light = false;
}
}
class WaterOn extends DTask {
WaterOn(long initialDelay, long period) {
super(initialDelay, period);
}

public void run() {
// Put hardware control code here.
System.out.println("Turning greenhouse water on");
water = true;
}
}
class WaterOff extends DTask {
WaterOff(long initialDelay, long period) {
super(initialDelay, period);
}

public void run() {
// Put hardware control code here.
System.out.println("Turning greenhouse water off");
water = false;
}
}
class ThermostatNight extends DTask {
ThermostatNight(long initialDelay, long period) {
super(initialDelay, period);
}

public void run() {
// Put hardware control code here.
System.out.println("Thermostat to night setting");
setThermostat("Night");
}
}
class ThermostatDay extends DTask {
ThermostatDay(long initialDelay, long period) {
super(initialDelay, period);
}
public void run() {
// Put hardware control code here.
System.out.println("Thermostat to day setting");
setThermostat("Day");
}
}
class Bell extends DTask {
Bell(long initialDelay, long period) {
super(initialDelay, period);
}
public void run() { System.out.println("Bing!"); }
}
class Terminate extends DTask {
ExecutorService exec;
Terminate(long initialDelay, long period,ExecutorService exec) {
super(initialDelay, period);
this.exec=exec;
}
public void run() {
System.out.println("Terminating");
// Must start a separate task to do this job,
// since the scheduler has been shut down:
exec.shutdownNow();
new Thread() {
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;
}
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<DataPoint>());
class CollectData extends DTask {
CollectData(long initialDelay, long period) {
super(initialDelay, period);
}

public void run() {
System.out.println("Collecting data");
synchronized(GreenhouseScheduler33.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));
}
}
}
class DelayedTaskConsumer implements Runnable{
private DelayQueue<DTask> queue;
DelayedTaskConsumer(DelayQueue<DTask> queue){
this.queue=queue;
}
public void run(){
try {
while(!Thread.interrupted()){
DTask t=queue.take();
t.run();
//将取出对象延迟时间设置后重新放入队列
t.setDelay();
queue.put(t);
} // Run task with the current thread
} catch(InterruptedException e) {
// Acceptable way to exit
}
print("Finished DelayedTaskConsumer");
}
}
public static void main(String[] args) {
DelayQueue<DTask> queue=new DelayQueue<DTask>();
GreenhouseScheduler33 gh = new GreenhouseScheduler33();
ExecutorService exec=Executors.newCachedThreadPool();
queue.put(gh.new Bell(0, 1000));
queue.put(gh.new ThermostatNight(0, 2000));
queue.put(gh.new LightOn(0, 200));
queue.put(gh.new LightOff(0, 400));
queue.put(gh.new WaterOn(0, 600));
queue.put(gh.new WaterOff(0, 800));
queue.put(gh.new ThermostatDay(0, 1400));
queue.put(gh.new CollectData(500, 500));
//terminate
queue.put(gh.new Terminate(3000,3000,exec));
exec.execute(gh.new DelayedTaskConsumer(queue));
}
}
---------------------------------------------------------------
//output:
/*Bing!
Thermostat to night setting
Turning on lights
Turning off lights
Turning greenhouse water on
Turning greenhouse water off
Thermostat to day setting
Turning on lights
Turning off lights
Collecting data
Turning on lights
Turning greenhouse water on
Turning on lights
Turning greenhouse water off
Turning off lights
Bing!
Collecting data
Turning on lights
Turning greenhouse water on
Turning off lights
Turning on lights
Thermostat to day setting
Collecting data
Turning on lights
Turning greenhouse water off
Turning off lights
Turning greenhouse water on
Thermostat to night setting
Bing!
Turning on lights
Collecting data
Turning off lights
Turning on lights
Turning greenhouse water on
Turning on lights
Collecting data
Turning greenhouse water off
Turning off lights
Turning on lights
Thermostat to day setting
Terminating
Finished DelayedTaskConsumer
Sat Mar 05 15:00:00 GMT 2011 temperature: 66.4 humidity: 50.05
Sat Mar 05 15:30:00 GMT 2011 temperature: 68.0 humidity: 50.47
Sat Mar 05 16:00:00 GMT 2011 temperature: 69.7 humidity: 51.42
Sat Mar 05 16:30:00 GMT 2011 temperature: 70.8 humidity: 50.87
Sat Mar 05 17:00:00 GMT 2011 temperature: 72.0 humidity: 50.32
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值